Merge "Extract getIntentUser function in ResolverActivity" into tm-qpr-dev
diff --git a/Android.bp b/Android.bp
index df6fdaa..caec3a2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -151,6 +151,9 @@
     visibility: [
         // DO NOT ADD ANY MORE ENTRIES TO THIS LIST
         "//external/robolectric-shadows:__subpackages__",
+        //This will eventually replace the item above, and serves the
+        //same purpose.
+        "//external/robolectric:__subpackages__",
         "//frameworks/layoutlib:__subpackages__",
     ],
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 81c3e89..d24b677 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1684,7 +1684,7 @@
                 .isOnBackInvokedCallbackEnabled(this);
         if (aheadOfTimeBack) {
             // Add onBackPressed as default back behavior.
-            mDefaultBackCallback = this::navigateBack;
+            mDefaultBackCallback = this::onBackInvoked;
             getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
         }
     }
@@ -4002,22 +4002,19 @@
         if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
             return;
         }
-        navigateBack();
+        onBackInvoked();
     }
 
-    private void navigateBack() {
-        if (!isTaskRoot()) {
-            // If the activity is not the root of the task, allow finish to proceed normally.
-            finishAfterTransition();
-            return;
-        }
-        // Inform activity task manager that the activity received a back press while at the
-        // root of the task. This call allows ActivityTaskManager to intercept or move the task
-        // to the back.
-        ActivityClient.getInstance().onBackPressedOnTaskRoot(mToken,
+    private void onBackInvoked() {
+        // Inform activity task manager that the activity received a back press.
+        // This call allows ActivityTaskManager to intercept or move the task
+        // to the back when needed.
+        ActivityClient.getInstance().onBackPressed(mToken,
                 new RequestFinishCallback(new WeakReference<>(this)));
 
-        getAutofillClientController().onActivityBackPressed(mIntent);
+        if (isTaskRoot()) {
+            getAutofillClientController().onActivityBackPressed(mIntent);
+        }
     }
 
     /**
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index d1e6780..4cf48ab 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -525,9 +525,9 @@
         }
     }
 
-    void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
+    void onBackPressed(IBinder token, IRequestFinishCallback callback) {
         try {
-            getActivityClientController().onBackPressedOnTaskRoot(token, callback);
+            getActivityClientController().onBackPressed(token, callback);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 9aa67bc..62481ba 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -145,10 +145,9 @@
     void unregisterRemoteAnimations(in IBinder token);
 
     /**
-     * Reports that an Activity received a back key press when there were no additional activities
-     * on the back stack.
+     * Reports that an Activity received a back key press.
      */
-    oneway void onBackPressedOnTaskRoot(in IBinder activityToken,
+    oneway void onBackPressed(in IBinder activityToken,
             in IRequestFinishCallback callback);
 
     /** Reports that the splash screen view has attached to activity.  */
diff --git a/core/java/android/app/IRequestFinishCallback.aidl b/core/java/android/app/IRequestFinishCallback.aidl
index 22c20c8..72426df 100644
--- a/core/java/android/app/IRequestFinishCallback.aidl
+++ b/core/java/android/app/IRequestFinishCallback.aidl
@@ -18,7 +18,7 @@
 
 /**
  * This callback allows ActivityTaskManager to ask the calling Activity
- * to finish in response to a call to onBackPressedOnTaskRoot.
+ * to finish in response to a call to onBackPressed.
  *
  * {@hide}
  */
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 2e83308..99f864c 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -57,8 +57,7 @@
  * @deprecated IntentService is subject to all the
  *   <a href="{@docRoot}about/versions/oreo/background.html">background execution limits</a>
  *   imposed with Android 8.0 (API level 26). Consider using {@link androidx.work.WorkManager}
- *   or {@link androidx.core.app.JobIntentService}, which uses jobs
- *   instead of services when running on Android 8.0 or higher.
+ *   instead.
  */
 @Deprecated
 public abstract class IntentService extends Service {
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index ae0fc09..719b5b6 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -229,6 +229,8 @@
     public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1;
     /** @hide */
     public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2;
+    /** @hide */
+    public static final int CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE = 3;
 
     /**
      * Session flag for {@link #registerSessionListener} indicating the listener
diff --git a/core/java/android/app/search/SearchSession.java b/core/java/android/app/search/SearchSession.java
index 2cd1d96..10db337 100644
--- a/core/java/android/app/search/SearchSession.java
+++ b/core/java/android/app/search/SearchSession.java
@@ -23,9 +23,11 @@
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.util.Log;
 
 import dalvik.system.CloseGuard;
@@ -70,7 +72,7 @@
  * @hide
  */
 @SystemApi
-public final class SearchSession implements AutoCloseable{
+public final class SearchSession implements AutoCloseable {
 
     private static final String TAG = SearchSession.class.getSimpleName();
     private static final boolean DEBUG = false;
@@ -229,7 +231,14 @@
                 if (DEBUG) {
                     Log.d(TAG, "CallbackWrapper.onResult result=" + result.getList());
                 }
-                mExecutor.execute(() -> mCallback.accept(result.getList()));
+                List<SearchTarget> list = result.getList();
+                if (list.size() > 0) {
+                    Bundle bundle = list.get(0).getExtras();
+                    if (bundle != null) {
+                        bundle.putLong("key_ipc_start", SystemClock.elapsedRealtime());
+                    }
+                }
+                mExecutor.execute(() -> mCallback.accept(list));
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index a645ae4..3a07bb0 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -160,4 +160,9 @@
     void registerBatteryListener(int deviceId, IInputDeviceBatteryListener listener);
 
     void unregisterBatteryListener(int deviceId, IInputDeviceBatteryListener listener);
+
+    @EnforcePermission("MONITOR_INPUT")
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+            + "android.Manifest.permission.MONITOR_INPUT)")
+    void pilferPointers(IBinder inputChannelToken);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 97812ce..1cf3bb5 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1819,6 +1819,34 @@
     }
 
     /**
+     * Pilfer pointers from an input channel.
+     *
+     * Takes all the current pointer event streams that are currently being sent to the given
+     * input channel and generates appropriate cancellations for all other windows that are
+     * receiving these pointers.
+     *
+     * This API is intended to be used in conjunction with spy windows. When a spy window pilfers
+     * pointers, the foreground windows and all other spy windows that are receiving any of the
+     * pointers that are currently being dispatched to the pilfering window will have those pointers
+     * canceled. Only the pilfering window will continue to receive events for the affected pointers
+     * until the pointer is lifted.
+     *
+     * This method should be used with caution as unexpected pilfering can break fundamental user
+     * interactions.
+     *
+     * @see android.os.InputConfig#SPY
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MONITOR_INPUT)
+    public void pilferPointers(IBinder inputChannelToken) {
+        try {
+            mIm.pilferPointers(inputChannelToken);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Removes a previously registered battery listener for an input device.
      * @see #addInputDeviceBatteryListener(int, Executor, InputDeviceBatteryListener)
      * @hide
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 6091bf9..bf72b1d 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.hardware.vibrator.IVibrator;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Range;
@@ -313,8 +314,14 @@
         private static final float EPSILON = 1e-5f;
 
         public MultiVibratorInfo(VibratorInfo[] vibrators) {
+            // Need to use an extra constructor to share the computation in super initialization.
+            this(vibrators, frequencyProfileIntersection(vibrators));
+        }
+
+        private MultiVibratorInfo(VibratorInfo[] vibrators,
+                VibratorInfo.FrequencyProfile mergedProfile) {
             super(/* id= */ -1,
-                    capabilitiesIntersection(vibrators),
+                    capabilitiesIntersection(vibrators, mergedProfile.isEmpty()),
                     supportedEffectsIntersection(vibrators),
                     supportedBrakingIntersection(vibrators),
                     supportedPrimitivesAndDurationsIntersection(vibrators),
@@ -323,14 +330,19 @@
                     integerLimitIntersection(vibrators, VibratorInfo::getPwlePrimitiveDurationMax),
                     integerLimitIntersection(vibrators, VibratorInfo::getPwleSizeMax),
                     floatPropertyIntersection(vibrators, VibratorInfo::getQFactor),
-                    frequencyProfileIntersection(vibrators));
+                    mergedProfile);
         }
 
-        private static int capabilitiesIntersection(VibratorInfo[] infos) {
+        private static int capabilitiesIntersection(VibratorInfo[] infos,
+                boolean frequencyProfileIsEmpty) {
             int intersection = ~0;
             for (VibratorInfo info : infos) {
                 intersection &= info.getCapabilities();
             }
+            if (frequencyProfileIsEmpty) {
+                // Revoke frequency control if the merged frequency profile ended up empty.
+                intersection &= ~IVibrator.CAP_FREQUENCY_CONTROL;
+            }
             return intersection;
         }
 
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 98fe666..516d80e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -313,6 +313,13 @@
     public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
 
     /**
+     * Namespace for all Kernel Multi-Gen LRU feature.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_MGLRU_NATIVE = "mglru_native";
+
+    /**
      * Namespace for all netd related features.
      *
      * @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a955dbb..1110ef4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10309,11 +10309,11 @@
         public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
 
         /**
-         * The duration of timeout, in milliseconds, to switch from a non-primary user to the
-         * primary user when the device is docked.
+         * The duration of timeout, in milliseconds, to switch from a non-Dock User to the
+         * Dock User when the device is docked.
          * @hide
          */
-        public static final String TIMEOUT_TO_USER_ZERO = "timeout_to_user_zero";
+        public static final String TIMEOUT_TO_DOCK_USER = "timeout_to_dock_user";
 
         /**
          * Backup manager behavioral parameters.
@@ -18441,6 +18441,9 @@
     /**
      * Activity Action: For system or preinstalled apps to show their {@link Activity} embedded
      * in Settings app on large screen devices.
+     *
+     * Developers should resolve the Intent action before using it.
+     *
      * <p>
      *     Input: {@link #EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI} must be included to
      * specify the intent for the activity which will be embedded in Settings app.
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 47b16a3..d2a4ae2 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -55,6 +55,20 @@
             "android.service.controls.ControlsProviderService";
 
     /**
+     * Manifest metadata to show a custom embedded activity as part of device controls.
+     *
+     * The value of this metadata must be the {@link ComponentName} as a string of an activity in
+     * the same package that will be launched as part of a TaskView.
+     *
+     * The activity must be exported, enabled and protected by
+     * {@link Manifest.permission.BIND_CONTROLS}.
+     *
+     * @hide
+     */
+    public static final String META_DATA_PANEL_ACTIVITY =
+            "android.service.controls.META_DATA_PANEL_ACTIVITY";
+
+    /**
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index aa45c20..6e8198b 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -49,6 +49,17 @@
             mShowComplications = shouldShowComplications;
             onStartDream(layoutParams);
         }
+
+        @Override
+        public void wakeUp() {
+            onWakeUp(() -> {
+                try {
+                    mDreamOverlayCallback.onWakeUpComplete();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Could not notify dream of wakeUp:" + e);
+                }
+            });
+        }
     };
 
     IDreamOverlayCallback mDreamOverlayCallback;
@@ -71,6 +82,17 @@
     public abstract void onStartDream(@NonNull WindowManager.LayoutParams layoutParams);
 
     /**
+     * This method is overridden by implementations to handle when the dream has been requested
+     * to wakeup. This allows any overlay animations to run.
+     *
+     * @param onCompleteCallback The callback to trigger to notify the dream service that the
+     *                           overlay has completed waking up.
+     * @hide
+     */
+    public void onWakeUp(@NonNull Runnable onCompleteCallback) {
+    }
+
+    /**
      * This method is invoked to request the dream exit.
      */
     public final void requestExit() {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 32bdf79..8b9852a 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -312,7 +312,14 @@
         @Override
         public void onExitRequested() {
             // Simply finish dream when exit is requested.
-            finish();
+            mHandler.post(() -> finish());
+        }
+
+        @Override
+        public void onWakeUpComplete() {
+            // Finish the dream once overlay animations are complete. Execute on handler since
+            // this is coming in on the overlay binder.
+            mHandler.post(() -> finish());
         }
     };
 
@@ -975,7 +982,18 @@
      * </p>
      */
     public void onWakeUp() {
-        finish();
+        if (mOverlayConnection != null) {
+            mOverlayConnection.addConsumer(overlay -> {
+                try {
+                    overlay.wakeUp();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error waking the overlay service", e);
+                    finish();
+                }
+            });
+        } else {
+            finish();
+        }
     }
 
     /** {@inheritDoc} */
@@ -1294,7 +1312,7 @@
         if (!mWindowless) {
             Intent i = new Intent(this, DreamActivity.class);
             i.setPackage(getApplicationContext().getPackageName());
-            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            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()));
diff --git a/core/java/android/service/dreams/IDreamOverlay.aidl b/core/java/android/service/dreams/IDreamOverlay.aidl
index 05ebbfe..7aeceb2c 100644
--- a/core/java/android/service/dreams/IDreamOverlay.aidl
+++ b/core/java/android/service/dreams/IDreamOverlay.aidl
@@ -38,4 +38,7 @@
     */
     void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
         in String dreamComponent, in boolean shouldShowComplications);
+
+    /** Called when the dream is waking, to do any exit animations */
+    void wakeUp();
 }
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index ec76a33..4ad63f1 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -28,4 +28,7 @@
     * Invoked to request the dream exit.
     */
     void onExitRequested();
+
+    /** Invoked when the dream overlay wakeUp animation is complete. */
+    void onWakeUpComplete();
 }
\ No newline at end of file
diff --git a/core/java/android/service/voice/HotwordAudioStream.aidl b/core/java/android/service/voice/HotwordAudioStream.aidl
new file mode 100644
index 0000000..9550c83
--- /dev/null
+++ b/core/java/android/service/voice/HotwordAudioStream.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+parcelable HotwordAudioStream;
diff --git a/core/java/android/service/voice/HotwordAudioStream.java b/core/java/android/service/voice/HotwordAudioStream.java
new file mode 100644
index 0000000..5442860
--- /dev/null
+++ b/core/java/android/service/voice/HotwordAudioStream.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.AudioTimestamp;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+
+import java.util.Objects;
+
+/**
+ * Represents an audio stream supporting the hotword detection.
+ *
+ * @hide
+ */
+public final class HotwordAudioStream implements Parcelable {
+
+    /**
+     * The {@link AudioFormat} of the audio stream.
+     */
+    @NonNull
+    @UnsupportedAppUsage
+    private final AudioFormat mAudioFormat;
+
+    /**
+     * This stream starts with the audio bytes used for hotword detection, but continues streaming
+     * the audio until the stream is shutdown by the {@link HotwordDetectionService}.
+     */
+    @NonNull
+    @UnsupportedAppUsage
+    private final ParcelFileDescriptor mAudioStreamParcelFileDescriptor;
+
+    /**
+     * The timestamp when the audio stream was captured by the Audio platform.
+     *
+     * <p>
+     * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
+     * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
+     * field by {@link AudioRecord#getTimestamp}.
+     * </p>
+     *
+     * <p>
+     * This timestamp can be used in conjunction with the
+     * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
+     * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
+     * timestamps.
+     * </p>
+     *
+     * @see #getAudioStreamParcelFileDescriptor()
+     */
+    @Nullable
+    @UnsupportedAppUsage
+    private final AudioTimestamp mTimestamp;
+
+    private static AudioTimestamp defaultTimestamp() {
+        return null;
+    }
+
+    /**
+     * The metadata associated with the audio stream.
+     */
+    @NonNull
+    @UnsupportedAppUsage
+    private final PersistableBundle mMetadata;
+
+    private static PersistableBundle defaultMetadata() {
+        return new PersistableBundle();
+    }
+
+    private String timestampToString() {
+        if (mTimestamp == null) {
+            return "";
+        }
+        return "TimeStamp:"
+                + " framePos=" + mTimestamp.framePosition
+                + " nanoTime=" + mTimestamp.nanoTime;
+    }
+
+    private void parcelTimestamp(Parcel dest, int flags) {
+        if (mTimestamp != null) {
+            // mTimestamp is not null, we write it to the parcel, set true.
+            dest.writeBoolean(true);
+            dest.writeLong(mTimestamp.framePosition);
+            dest.writeLong(mTimestamp.nanoTime);
+        } else {
+            // mTimestamp is null, we don't write any value out, set false.
+            dest.writeBoolean(false);
+        }
+    }
+
+    @Nullable
+    private static AudioTimestamp unparcelTimestamp(Parcel in) {
+        // If it is true, it means we wrote the value to the parcel before, parse it.
+        // Otherwise, return null.
+        if (in.readBoolean()) {
+            final AudioTimestamp timeStamp = new AudioTimestamp();
+            timeStamp.framePosition = in.readLong();
+            timeStamp.nanoTime = in.readLong();
+            return timeStamp;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Provides an instance of {@link Builder} with state corresponding to this instance.
+     * @hide
+     */
+    public Builder buildUpon() {
+        return new Builder(mAudioFormat, mAudioStreamParcelFileDescriptor)
+            .setTimestamp(mTimestamp)
+            .setMetadata(mMetadata);
+    }
+
+    /* package-private */
+    HotwordAudioStream(
+            @NonNull AudioFormat audioFormat,
+            @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor,
+            @Nullable AudioTimestamp timestamp,
+            @NonNull PersistableBundle metadata) {
+        this.mAudioFormat = audioFormat;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioFormat);
+        this.mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioStreamParcelFileDescriptor);
+        this.mTimestamp = timestamp;
+        this.mMetadata = metadata;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMetadata);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The {@link AudioFormat} of the audio stream.
+     */
+    @UnsupportedAppUsage
+    @NonNull
+    public AudioFormat getAudioFormat() {
+        return mAudioFormat;
+    }
+
+    /**
+     * This stream starts with the audio bytes used for hotword detection, but continues streaming
+     * the audio until the stream is shutdown by the {@link HotwordDetectionService}.
+     */
+    @UnsupportedAppUsage
+    @NonNull
+    public ParcelFileDescriptor getAudioStreamParcelFileDescriptor() {
+        return mAudioStreamParcelFileDescriptor;
+    }
+
+    /**
+     * The timestamp when the audio stream was captured by the Audio platform.
+     *
+     * <p>
+     * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
+     * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
+     * field by {@link AudioRecord#getTimestamp}.
+     * </p>
+     *
+     * <p>
+     * This timestamp can be used in conjunction with the
+     * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
+     * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
+     * timestamps.
+     * </p>
+     *
+     * @see #getAudioStreamParcelFileDescriptor()
+     */
+    @UnsupportedAppUsage
+    @Nullable
+    public AudioTimestamp getTimestamp() {
+        return mTimestamp;
+    }
+
+    /**
+     * The metadata associated with the audio stream.
+     */
+    @UnsupportedAppUsage
+    @NonNull
+    public PersistableBundle getMetadata() {
+        return mMetadata;
+    }
+
+    @Override
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "HotwordAudioStream { "
+                + "audioFormat = " + mAudioFormat + ", "
+                + "audioStreamParcelFileDescriptor = " + mAudioStreamParcelFileDescriptor + ", "
+                + "timestamp = " + timestampToString() + ", "
+                + "metadata = " + mMetadata + " }";
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(HotwordAudioStream other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        HotwordAudioStream that = (HotwordAudioStream) o;
+        //noinspection PointlessBooleanExpression
+        return Objects.equals(mAudioFormat, that.mAudioFormat)
+                && Objects.equals(mAudioStreamParcelFileDescriptor,
+                that.mAudioStreamParcelFileDescriptor)
+                && Objects.equals(mTimestamp, that.mTimestamp)
+                && Objects.equals(mMetadata, that.mMetadata);
+    }
+
+    @Override
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + Objects.hashCode(mAudioFormat);
+        _hash = 31 * _hash + Objects.hashCode(mAudioStreamParcelFileDescriptor);
+        _hash = 31 * _hash + Objects.hashCode(mTimestamp);
+        _hash = 31 * _hash + Objects.hashCode(mMetadata);
+        return _hash;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mTimestamp != null) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeTypedObject(mAudioFormat, flags);
+        dest.writeTypedObject(mAudioStreamParcelFileDescriptor, flags);
+        parcelTimestamp(dest, flags);
+        dest.writeTypedObject(mMetadata, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    /* package-private */
+    HotwordAudioStream(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        AudioFormat audioFormat = (AudioFormat) in.readTypedObject(AudioFormat.CREATOR);
+        ParcelFileDescriptor audioStreamParcelFileDescriptor =
+                (ParcelFileDescriptor) in.readTypedObject(ParcelFileDescriptor.CREATOR);
+        AudioTimestamp timestamp = unparcelTimestamp(in);
+        PersistableBundle metadata = (PersistableBundle) in.readTypedObject(
+                PersistableBundle.CREATOR);
+
+        this.mAudioFormat = audioFormat;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioFormat);
+        this.mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioStreamParcelFileDescriptor);
+        this.mTimestamp = timestamp;
+        this.mMetadata = metadata;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMetadata);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<HotwordAudioStream> CREATOR =
+            new Parcelable.Creator<HotwordAudioStream>() {
+                @Override
+                public HotwordAudioStream[] newArray(int size) {
+                    return new HotwordAudioStream[size];
+                }
+
+                @Override
+                public HotwordAudioStream createFromParcel(@NonNull Parcel in) {
+                    return new HotwordAudioStream(in);
+                }
+            };
+
+    /**
+     * A builder for {@link HotwordAudioStream}
+     */
+    @SuppressWarnings("WeakerAccess")
+    public static final class Builder {
+
+        @NonNull
+        private AudioFormat mAudioFormat;
+        @NonNull
+        private ParcelFileDescriptor mAudioStreamParcelFileDescriptor;
+        @Nullable
+        private AudioTimestamp mTimestamp;
+        @NonNull
+        private PersistableBundle mMetadata;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param audioFormat                     The {@link AudioFormat} of the audio stream.
+         * @param audioStreamParcelFileDescriptor This stream starts with the audio bytes used for
+         *                                        hotword detection, but continues streaming
+         *                                        the audio until the stream is shutdown by the
+         *                                        {@link HotwordDetectionService}.
+         */
+        @UnsupportedAppUsage
+        public Builder(
+                @NonNull AudioFormat audioFormat,
+                @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor) {
+            mAudioFormat = audioFormat;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mAudioFormat);
+            mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mAudioStreamParcelFileDescriptor);
+        }
+
+        /**
+         * The {@link AudioFormat} of the audio stream.
+         */
+        @UnsupportedAppUsage
+        @NonNull
+        public Builder setAudioFormat(@NonNull AudioFormat value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mAudioFormat = value;
+            return this;
+        }
+
+        /**
+         * This stream starts with the audio bytes used for hotword detection, but continues
+         * streaming
+         * the audio until the stream is shutdown by the {@link HotwordDetectionService}.
+         */
+        @UnsupportedAppUsage
+        @NonNull
+        public Builder setAudioStreamParcelFileDescriptor(@NonNull ParcelFileDescriptor value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mAudioStreamParcelFileDescriptor = value;
+            return this;
+        }
+
+        /**
+         * The timestamp when the audio stream was captured by the Audio platform.
+         *
+         * <p>
+         * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
+         * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
+         * field by {@link AudioRecord#getTimestamp}.
+         * </p>
+         *
+         * <p>
+         * This timestamp can be used in conjunction with the
+         * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
+         * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
+         * timestamps.
+         * </p>
+         *
+         * @see #getAudioStreamParcelFileDescriptor()
+         */
+        @UnsupportedAppUsage
+        @NonNull
+        public Builder setTimestamp(@NonNull AudioTimestamp value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mTimestamp = value;
+            return this;
+        }
+
+        /**
+         * The metadata associated with the audio stream.
+         */
+        @UnsupportedAppUsage
+        @NonNull
+        public Builder setMetadata(@NonNull PersistableBundle value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mMetadata = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        @UnsupportedAppUsage
+        @NonNull
+        public HotwordAudioStream build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mTimestamp = defaultTimestamp();
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mMetadata = defaultMetadata();
+            }
+            HotwordAudioStream o = new HotwordAudioStream(
+                    mAudioFormat,
+                    mAudioStreamParcelFileDescriptor,
+                    mTimestamp,
+                    mMetadata);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x10) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+}
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index ab71459..c3d58b7 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.media.AudioRecord;
 import android.media.MediaSyncEvent;
@@ -31,6 +32,11 @@
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -96,14 +102,42 @@
     private static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE = 63;
 
     /**
-     * The bundle key for proximity value
+     * The bundle key for proximity
      *
      * TODO(b/238896013): Move the proximity logic out of bundle to proper API.
+     */
+    private static final String EXTRA_PROXIMITY =
+            "android.service.voice.extra.PROXIMITY";
+
+    /**
+     * Users’ proximity is unknown (proximity sensing was inconclusive and is unsupported).
      *
      * @hide
      */
-    public static final String EXTRA_PROXIMITY_METERS =
-            "android.service.voice.extra.PROXIMITY_METERS";
+    public static final int PROXIMITY_UNKNOWN = -1;
+
+    /**
+     * Proximity value that represents that the object is near.
+     *
+     * @hide
+     */
+    public static final int PROXIMITY_NEAR = 1;
+
+    /**
+     * Proximity value that represents that the object is far.
+     *
+     * @hide
+     */
+    public static final int PROXIMITY_FAR = 2;
+
+    /** @hide */
+    @IntDef(prefix = {"PROXIMITY"}, value = {
+            PROXIMITY_UNKNOWN,
+            PROXIMITY_NEAR,
+            PROXIMITY_FAR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ProximityValue {}
 
     /** Confidence level in the trigger outcome. */
     @HotwordConfidenceLevelValue
@@ -196,6 +230,17 @@
     }
 
     /**
+     * The list of the audio streams containing audio bytes that were used for hotword detection.
+     *
+     * @hide
+     */
+    @NonNull
+    private final List<HotwordAudioStream> mAudioStreams;
+    private static List<HotwordAudioStream> defaultAudioStreams() {
+        return Collections.emptyList();
+    }
+
+    /**
      * App-specific extras to support trigger.
      *
      * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
@@ -208,12 +253,14 @@
      * versions of Android.
      *
      * <p>After the trigger happens, a special case of proximity-related extra, with the key of
-     * 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
-     * will be stored to enable proximity logic. The proximity meters is provided by the system,
-     * on devices that support detecting proximity of nearby users, to help disambiguate which
-     * nearby device should respond. When the proximity is unknown, the proximity value will not
-     * be stored. This mapping will be excluded from the max bundle size calculation because this
-     * mapping is included after the result is returned from the hotword detector service.
+     * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
+     * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
+     * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
+     * proximity. The proximity value is provided by the system, on devices that support detecting
+     * proximity of nearby users, to help disambiguate which nearby device should respond. When the
+     * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
+     * from the max bundle size calculation because this mapping is included after the result is
+     * returned from the hotword detector service.
      *
      * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
      * that can be used to communicate with other processes.
@@ -336,16 +383,16 @@
             // Remove the proximity key from the bundle before checking the bundle size. The
             // proximity value is added after the privileged module and can avoid the
             // maxBundleSize limitation.
-            if (mExtras.containsKey(EXTRA_PROXIMITY_METERS)) {
-                double proximityMeters = mExtras.getDouble(EXTRA_PROXIMITY_METERS);
-                mExtras.remove(EXTRA_PROXIMITY_METERS);
+            if (mExtras.containsKey(EXTRA_PROXIMITY)) {
+                int proximityValue = mExtras.getInt(EXTRA_PROXIMITY);
+                mExtras.remove(EXTRA_PROXIMITY);
                 // Skip checking parcelable size if the new bundle size is 0. Newly empty bundle
                 // has parcelable size of 4, but the default bundle has parcelable size of 0.
                 if (mExtras.size() > 0) {
                     Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
                             getMaxBundleSize(), "extras");
                 }
-                mExtras.putDouble(EXTRA_PROXIMITY_METERS, proximityMeters);
+                mExtras.putInt(EXTRA_PROXIMITY, proximityValue);
             } else {
                 Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
                         getMaxBundleSize(), "extras");
@@ -353,6 +400,90 @@
         }
     }
 
+    /**
+     * The list of the audio streams containing audio bytes that were used for hotword detection.
+     *
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public @NonNull List<HotwordAudioStream> getAudioStreams() {
+        return List.copyOf(mAudioStreams);
+    }
+
+    @DataClass.Suppress("addAudioStreams")
+    abstract static class BaseBuilder {
+        /**
+         * The list of the audio streams containing audio bytes that were used for hotword
+         * detection.
+         *
+         * @hide
+         */
+        @UnsupportedAppUsage
+        public @NonNull Builder setAudioStreams(@NonNull List<HotwordAudioStream> value) {
+            Objects.requireNonNull(value, "value should not be null");
+            final Builder builder = (Builder) this;
+            // If the code gen flag in build() is changed, we must update the flag e.g. 0x200 here.
+            builder.mBuilderFieldsSet |= 0x200;
+            builder.mAudioStreams = List.copyOf(value);
+            return builder;
+        }
+    }
+
+    /**
+     * Provides an instance of {@link Builder} with state corresponding to this instance.
+     * @hide
+     */
+    public Builder buildUpon() {
+        return new Builder()
+            .setConfidenceLevel(mConfidenceLevel)
+            .setMediaSyncEvent(mMediaSyncEvent)
+            .setHotwordOffsetMillis(mHotwordOffsetMillis)
+            .setHotwordDurationMillis(mHotwordDurationMillis)
+            .setAudioChannel(mAudioChannel)
+            .setHotwordDetectionPersonalized(mHotwordDetectionPersonalized)
+            .setScore(mScore)
+            .setPersonalizedScore(mPersonalizedScore)
+            .setHotwordPhraseId(mHotwordPhraseId)
+            .setAudioStreams(mAudioStreams)
+            .setExtras(mExtras);
+    }
+
+    /**
+     * Adds proximity level, either near or far, that is mapped for the given distance into
+     * the bundle. The proximity value is provided by the system, on devices that support detecting
+     * proximity of nearby users, to help disambiguate which nearby device should respond.
+     * This mapping will be excluded from the max bundle size calculation because this mapping is
+     * included after the result is returned from the hotword detector service. The value will not
+     * be included if the proximity was unknown.
+     *
+     * @hide
+     */
+    public void setProximity(double distance) {
+        int proximityLevel = convertToProximityLevel(distance);
+        if (proximityLevel != PROXIMITY_UNKNOWN) {
+            mExtras.putInt(EXTRA_PROXIMITY, proximityLevel);
+        }
+    }
+
+    /**
+     * Mapping of the proximity distance (meters) to proximity values, unknown, near, and far.
+     * Currently, this mapping is handled by HotwordDetectedResult because it handles just
+     * HotwordDetectionConnection which we know the mapping of. However, the mapping will need to
+     * move to a more centralized place once there are more clients.
+     *
+     * TODO(b/258531144): Move the proximity mapping to a central location
+     */
+    @ProximityValue
+    private int convertToProximityLevel(double distance) {
+        if (distance < 0) {
+            return PROXIMITY_UNKNOWN;
+        } else if (distance <= 3) {
+            return PROXIMITY_NEAR;
+        } else {
+            return PROXIMITY_FAR;
+        }
+    }
+
 
 
     // Code below generated by codegen v1.0.23.
@@ -378,7 +509,7 @@
         CONFIDENCE_LEVEL_HIGH,
         CONFIDENCE_LEVEL_VERY_HIGH
     })
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @Retention(RetentionPolicy.SOURCE)
     @DataClass.Generated.Member
     public @interface ConfidenceLevel {}
 
@@ -409,7 +540,7 @@
         LIMIT_HOTWORD_OFFSET_MAX_VALUE,
         LIMIT_AUDIO_CHANNEL_MAX_VALUE
     })
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @Retention(RetentionPolicy.SOURCE)
     @DataClass.Generated.Member
     /* package-private */ @interface Limit {}
 
@@ -425,6 +556,30 @@
         }
     }
 
+    /** @hide */
+    @IntDef(prefix = "PROXIMITY_", value = {
+        PROXIMITY_UNKNOWN,
+        PROXIMITY_NEAR,
+        PROXIMITY_FAR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @DataClass.Generated.Member
+    public @interface Proximity {}
+
+    /** @hide */
+    @DataClass.Generated.Member
+    public static String proximityToString(@Proximity int value) {
+        switch (value) {
+            case PROXIMITY_UNKNOWN:
+                    return "PROXIMITY_UNKNOWN";
+            case PROXIMITY_NEAR:
+                    return "PROXIMITY_NEAR";
+            case PROXIMITY_FAR:
+                    return "PROXIMITY_FAR";
+            default: return Integer.toHexString(value);
+        }
+    }
+
     @DataClass.Generated.Member
     /* package-private */ HotwordDetectedResult(
             @HotwordConfidenceLevelValue int confidenceLevel,
@@ -436,6 +591,7 @@
             int score,
             int personalizedScore,
             int hotwordPhraseId,
+            @NonNull List<HotwordAudioStream> audioStreams,
             @NonNull PersistableBundle extras) {
         this.mConfidenceLevel = confidenceLevel;
         com.android.internal.util.AnnotationValidations.validate(
@@ -448,6 +604,9 @@
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
         this.mHotwordPhraseId = hotwordPhraseId;
+        this.mAudioStreams = audioStreams;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioStreams);
         this.mExtras = extras;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mExtras);
@@ -547,12 +706,14 @@
      * versions of Android.
      *
      * <p>After the trigger happens, a special case of proximity-related extra, with the key of
-     * 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
-     * will be stored to enable proximity logic. The proximity meters is provided by the system,
-     * on devices that support detecting proximity of nearby users, to help disambiguate which
-     * nearby device should respond. When the proximity is unknown, the proximity value will not
-     * be stored. This mapping will be excluded from the max bundle size calculation because this
-     * mapping is included after the result is returned from the hotword detector service.
+     * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
+     * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
+     * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
+     * proximity. The proximity value is provided by the system, on devices that support detecting
+     * proximity of nearby users, to help disambiguate which nearby device should respond. When the
+     * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
+     * from the max bundle size calculation because this mapping is included after the result is
+     * returned from the hotword detector service.
      *
      * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
      * that can be used to communicate with other processes.
@@ -578,6 +739,7 @@
                 "score = " + mScore + ", " +
                 "personalizedScore = " + mPersonalizedScore + ", " +
                 "hotwordPhraseId = " + mHotwordPhraseId + ", " +
+                "audioStreams = " + mAudioStreams + ", " +
                 "extras = " + mExtras +
         " }";
     }
@@ -604,6 +766,7 @@
                 && mScore == that.mScore
                 && mPersonalizedScore == that.mPersonalizedScore
                 && mHotwordPhraseId == that.mHotwordPhraseId
+                && Objects.equals(mAudioStreams, that.mAudioStreams)
                 && Objects.equals(mExtras, that.mExtras);
     }
 
@@ -623,6 +786,7 @@
         _hash = 31 * _hash + mScore;
         _hash = 31 * _hash + mPersonalizedScore;
         _hash = 31 * _hash + mHotwordPhraseId;
+        _hash = 31 * _hash + Objects.hashCode(mAudioStreams);
         _hash = 31 * _hash + Objects.hashCode(mExtras);
         return _hash;
     }
@@ -645,6 +809,7 @@
         dest.writeInt(mScore);
         dest.writeInt(mPersonalizedScore);
         dest.writeInt(mHotwordPhraseId);
+        dest.writeParcelableList(mAudioStreams, flags);
         dest.writeTypedObject(mExtras, flags);
     }
 
@@ -669,6 +834,8 @@
         int score = in.readInt();
         int personalizedScore = in.readInt();
         int hotwordPhraseId = in.readInt();
+        List<HotwordAudioStream> audioStreams = new ArrayList<>();
+        in.readParcelableList(audioStreams, HotwordAudioStream.class.getClassLoader());
         PersistableBundle extras = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
 
         this.mConfidenceLevel = confidenceLevel;
@@ -682,6 +849,9 @@
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
         this.mHotwordPhraseId = hotwordPhraseId;
+        this.mAudioStreams = audioStreams;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAudioStreams);
         this.mExtras = extras;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mExtras);
@@ -708,7 +878,7 @@
      */
     @SuppressWarnings("WeakerAccess")
     @DataClass.Generated.Member
-    public static final class Builder {
+    public static final class Builder extends BaseBuilder {
 
         private @HotwordConfidenceLevelValue int mConfidenceLevel;
         private @Nullable MediaSyncEvent mMediaSyncEvent;
@@ -719,6 +889,7 @@
         private int mScore;
         private int mPersonalizedScore;
         private int mHotwordPhraseId;
+        private @NonNull List<HotwordAudioStream> mAudioStreams;
         private @NonNull PersistableBundle mExtras;
 
         private long mBuilderFieldsSet = 0L;
@@ -855,12 +1026,14 @@
          * versions of Android.
          *
          * <p>After the trigger happens, a special case of proximity-related extra, with the key of
-         * 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
-         * will be stored to enable proximity logic. The proximity meters is provided by the system,
-         * on devices that support detecting proximity of nearby users, to help disambiguate which
-         * nearby device should respond. When the proximity is unknown, the proximity value will not
-         * be stored. This mapping will be excluded from the max bundle size calculation because this
-         * mapping is included after the result is returned from the hotword detector service.
+         * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
+         * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
+         * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
+         * proximity. The proximity value is provided by the system, on devices that support detecting
+         * proximity of nearby users, to help disambiguate which nearby device should respond. When the
+         * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
+         * from the max bundle size calculation because this mapping is included after the result is
+         * returned from the hotword detector service.
          *
          * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
          * that can be used to communicate with other processes.
@@ -868,7 +1041,7 @@
         @DataClass.Generated.Member
         public @NonNull Builder setExtras(@NonNull PersistableBundle value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x200;
+            mBuilderFieldsSet |= 0x400;
             mExtras = value;
             return this;
         }
@@ -876,7 +1049,7 @@
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull HotwordDetectedResult build() {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x400; // Mark builder used
+            mBuilderFieldsSet |= 0x800; // Mark builder used
 
             if ((mBuilderFieldsSet & 0x1) == 0) {
                 mConfidenceLevel = defaultConfidenceLevel();
@@ -906,6 +1079,9 @@
                 mHotwordPhraseId = defaultHotwordPhraseId();
             }
             if ((mBuilderFieldsSet & 0x200) == 0) {
+                mAudioStreams = defaultAudioStreams();
+            }
+            if ((mBuilderFieldsSet & 0x400) == 0) {
                 mExtras = defaultExtras();
             }
             HotwordDetectedResult o = new HotwordDetectedResult(
@@ -918,12 +1094,13 @@
                     mScore,
                     mPersonalizedScore,
                     mHotwordPhraseId,
+                    mAudioStreams,
                     mExtras);
             return o;
         }
 
         private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x400) != 0) {
+            if ((mBuilderFieldsSet & 0x800) != 0) {
                 throw new IllegalStateException(
                         "This Builder should not be reused. Use a new Builder instance instead");
             }
@@ -931,10 +1108,10 @@
     }
 
     @DataClass.Generated(
-            time = 1658357814396L,
+            time = 1668528946960L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
-            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate static final  int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final  int LIMIT_AUDIO_CHANNEL_MAX_VALUE\npublic static final  java.lang.String EXTRA_PROXIMITY_METERS\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int sMaxBundleSize\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static  int getParcelableSize(android.os.Parcelable)\npublic static  int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static  int bitCount(long)\nprivate  void onConstructed()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate static final  int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final  int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final  java.lang.String EXTRA_PROXIMITY\npublic static final  int PROXIMITY_UNKNOWN\npublic static final  int PROXIMITY_NEAR\npublic static final  int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int sMaxBundleSize\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static  int getParcelableSize(android.os.Parcelable)\npublic static  int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static  int bitCount(long)\nprivate  void onConstructed()\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic  android.service.voice.HotwordDetectedResult.Builder buildUpon()\npublic  void setProximity(double)\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index eac3bee..302966a 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -92,7 +92,7 @@
      * TODO(b/247920386): Add TestApi annotation
      * @hide
      */
-    public static final boolean ENABLE_PROXIMITY_RESULT = false;
+    public static final boolean ENABLE_PROXIMITY_RESULT = true;
 
     /**
      * Indicates that the updated status is successful.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 5e86f2b..2175859 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -578,6 +578,7 @@
          */
         public void reportEngineShown(boolean waitForEngineShown) {
             if (mIWallpaperEngine.mShownReported) return;
+            Trace.beginSection("WPMS.reportEngineShown-" + waitForEngineShown);
             Log.d(TAG, "reportEngineShown: shouldWait=" + waitForEngineShown);
             if (!waitForEngineShown) {
                 Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN);
@@ -590,6 +591,7 @@
                     mCaller.sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(5));
                 }
             }
+            Trace.endSection();
         }
 
         /**
@@ -1259,7 +1261,9 @@
                             didSurface = true;
                             if (DEBUG) Log.v(TAG, "onSurfaceCreated("
                                     + mSurfaceHolder + "): " + this);
+                            Trace.beginSection("WPMS.Engine.onSurfaceCreated");
                             onSurfaceCreated(mSurfaceHolder);
+                            Trace.endSection();
                             SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                             if (callbacks != null) {
                                 for (SurfaceHolder.Callback c : callbacks) {
@@ -1285,8 +1289,10 @@
                                     + ", " + mCurWidth + ", " + mCurHeight
                                     + "): " + this);
                             didSurface = true;
+                            Trace.beginSection("WPMS.Engine.onSurfaceChanged");
                             onSurfaceChanged(mSurfaceHolder, mFormat,
                                     mCurWidth, mCurHeight);
+                            Trace.endSection();
                             SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                             if (callbacks != null) {
                                 for (SurfaceHolder.Callback c : callbacks) {
@@ -1303,11 +1309,15 @@
                             if (DEBUG) {
                                 Log.v(TAG, "dispatching insets=" + windowInsets);
                             }
+                            Trace.beginSection("WPMS.Engine.onApplyWindowInsets");
                             onApplyWindowInsets(windowInsets);
+                            Trace.endSection();
                         }
 
                         if (redrawNeeded) {
+                            Trace.beginSection("WPMS.Engine.onSurfaceRedrawNeeded");
                             onSurfaceRedrawNeeded(mSurfaceHolder);
+                            Trace.endSection();
                             SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                             if (callbacks != null) {
                                 for (SurfaceHolder.Callback c : callbacks) {
@@ -1332,11 +1342,15 @@
                                 // the state to get them to notice.
                                 if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
                                         + this);
+                                Trace.beginSection("WPMS.Engine.onVisibilityChanged-true");
                                 onVisibilityChanged(true);
+                                Trace.endSection();
                             }
                             if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
                                         + this);
+                            Trace.beginSection("WPMS.Engine.onVisibilityChanged-false");
                             onVisibilityChanged(false);
+                            Trace.endSection();
                         }
                     } finally {
                         mIsCreating = false;
@@ -1422,12 +1436,16 @@
             mDisplayInstallOrientation = mDisplay.getInstallOrientation();
 
             if (DEBUG) Log.v(TAG, "onCreate(): " + this);
+            Trace.beginSection("WPMS.Engine.onCreate");
             onCreate(mSurfaceHolder);
+            Trace.endSection();
 
             mInitializing = false;
 
             mReportedVisible = false;
+            Trace.beginSection("WPMS.Engine.updateSurface");
             updateSurface(false, false, false);
+            Trace.endSection();
         }
 
         /**
@@ -2237,14 +2255,15 @@
         public void reportShown() {
             if (!mShownReported) {
                 mShownReported = true;
+                Trace.beginSection("WPMS.mConnection.engineShown");
                 try {
                     mConnection.engineShown(this);
                     Log.d(TAG, "Wallpaper has updated the surface:"
                             + mWallpaperManager.getWallpaperInfo());
                 } catch (RemoteException e) {
                     Log.w(TAG, "Wallpaper host disappeared", e);
-                    return;
                 }
+                Trace.endSection();
             }
         }
 
@@ -2286,6 +2305,27 @@
             return mEngine == null ? null : SurfaceControl.mirrorSurface(mEngine.mSurfaceControl);
         }
 
+        private void doAttachEngine() {
+            Trace.beginSection("WPMS.onCreateEngine");
+            Engine engine = onCreateEngine();
+            Trace.endSection();
+            mEngine = engine;
+            Trace.beginSection("WPMS.mConnection.attachEngine-" + mDisplayId);
+            try {
+                mConnection.attachEngine(this, mDisplayId);
+            } catch (RemoteException e) {
+                engine.detach();
+                Log.w(TAG, "Wallpaper host disappeared", e);
+                return;
+            } finally {
+                Trace.endSection();
+            }
+            mActiveEngines.add(engine);
+            Trace.beginSection("WPMS.engine.attach");
+            engine.attach(this);
+            Trace.endSection();
+        }
+
         private void doDetachEngine() {
             mActiveEngines.remove(mEngine);
             mEngine.detach();
@@ -2311,21 +2351,15 @@
             }
             switch (message.what) {
                 case DO_ATTACH: {
-                    Engine engine = onCreateEngine();
-                    mEngine = engine;
-                    try {
-                        mConnection.attachEngine(this, mDisplayId);
-                    } catch (RemoteException e) {
-                        engine.detach();
-                        Log.w(TAG, "Wallpaper host disappeared", e);
-                        return;
-                    }
-                    mActiveEngines.add(engine);
-                    engine.attach(this);
+                    Trace.beginSection("WPMS.DO_ATTACH");
+                    doAttachEngine();
+                    Trace.endSection();
                     return;
                 }
                 case DO_DETACH: {
+                    Trace.beginSection("WPMS.DO_DETACH");
                     doDetachEngine();
+                    Trace.endSection();
                     return;
                 }
                 case DO_SET_DESIRED_SIZE: {
@@ -2406,7 +2440,9 @@
                     }
                 } break;
                 case MSG_REPORT_SHOWN: {
+                    Trace.beginSection("WPMS.MSG_REPORT_SHOWN");
                     reportShown();
+                    Trace.endSection();
                 } break;
                 default :
                     Log.w(TAG, "Unknown message type " + message.what);
@@ -2430,8 +2466,10 @@
         public void attach(IWallpaperConnection conn, IBinder windowToken,
                 int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                 int displayId, @SetWallpaperFlags int which) {
+            Trace.beginSection("WPMS.ServiceWrapper.attach");
             mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken,
                     windowType, isPreview, reqWidth, reqHeight, padding, displayId);
+            Trace.endSection();
         }
 
         @Override
@@ -2442,16 +2480,20 @@
 
     @Override
     public void onCreate() {
+        Trace.beginSection("WPMS.onCreate");
         super.onCreate();
+        Trace.endSection();
     }
 
     @Override
     public void onDestroy() {
+        Trace.beginSection("WPMS.onDestroy");
         super.onDestroy();
         for (int i=0; i<mActiveEngines.size(); i++) {
             mActiveEngines.get(i).detach();
         }
         mActiveEngines.clear();
+        Trace.endSection();
     }
 
     /**
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index e2c8a31..dc60edd 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -83,6 +83,12 @@
     private final boolean mIsTaskFragmentClearedForPip;
 
     /**
+     * Whether the last running activity of the TaskFragment was removed because it was reordered to
+     * front of the Task.
+     */
+    private final boolean mIsClearedForReorderActivityToFront;
+
+    /**
      * The maximum {@link ActivityInfo.WindowLayout#minWidth} and
      * {@link ActivityInfo.WindowLayout#minHeight} aggregated from the TaskFragment's child
      * activities.
@@ -96,7 +102,7 @@
             @NonNull Configuration configuration, int runningActivityCount,
             boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
             boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
-            @NonNull Point minimumDimensions) {
+            boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions) {
         mFragmentToken = requireNonNull(fragmentToken);
         mToken = requireNonNull(token);
         mConfiguration.setTo(configuration);
@@ -106,6 +112,7 @@
         mPositionInParent.set(positionInParent);
         mIsTaskClearedForReuse = isTaskClearedForReuse;
         mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
+        mIsClearedForReorderActivityToFront = isClearedForReorderActivityToFront;
         mMinimumDimensions.set(minimumDimensions);
     }
 
@@ -160,6 +167,11 @@
         return mIsTaskFragmentClearedForPip;
     }
 
+    /** @hide */
+    public boolean isClearedForReorderActivityToFront() {
+        return mIsClearedForReorderActivityToFront;
+    }
+
     @WindowingMode
     public int getWindowingMode() {
         return mConfiguration.windowConfiguration.getWindowingMode();
@@ -207,6 +219,7 @@
                 && mPositionInParent.equals(that.mPositionInParent)
                 && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
                 && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
+                && mIsClearedForReorderActivityToFront == that.mIsClearedForReorderActivityToFront
                 && mMinimumDimensions.equals(that.mMinimumDimensions);
     }
 
@@ -220,6 +233,7 @@
         mPositionInParent.readFromParcel(in);
         mIsTaskClearedForReuse = in.readBoolean();
         mIsTaskFragmentClearedForPip = in.readBoolean();
+        mIsClearedForReorderActivityToFront = in.readBoolean();
         mMinimumDimensions.readFromParcel(in);
     }
 
@@ -235,6 +249,7 @@
         mPositionInParent.writeToParcel(dest, flags);
         dest.writeBoolean(mIsTaskClearedForReuse);
         dest.writeBoolean(mIsTaskFragmentClearedForPip);
+        dest.writeBoolean(mIsClearedForReorderActivityToFront);
         mMinimumDimensions.writeToParcel(dest, flags);
     }
 
@@ -262,8 +277,9 @@
                 + " activities=" + mActivities
                 + " positionInParent=" + mPositionInParent
                 + " isTaskClearedForReuse=" + mIsTaskClearedForReuse
-                + " isTaskFragmentClearedForPip" + mIsTaskFragmentClearedForPip
-                + " minimumDimensions" + mMinimumDimensions
+                + " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
+                + " mIsClearedForReorderActivityToFront=" + mIsClearedForReorderActivityToFront
+                + " minimumDimensions=" + mMinimumDimensions
                 + "}";
     }
 
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index cfad1af..15be5f5 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -467,6 +467,23 @@
     }
 
     /**
+     * Sets whether a container is being drag-resized.
+     * When {@code true}, the client will reuse a single (larger) surface size to avoid
+     * continuous allocations on every size change.
+     *
+     * @param container WindowContainerToken of the task that changed its drag resizing state
+     * @hide
+     */
+    @NonNull
+    public WindowContainerTransaction setDragResizing(@NonNull WindowContainerToken container,
+            boolean dragResizing) {
+        final Change change = getOrCreateChange(container.asBinder());
+        change.mChangeMask |= Change.CHANGE_DRAG_RESIZING;
+        change.mDragResizing = dragResizing;
+        return this;
+    }
+
+    /**
      * Sends a pending intent in sync.
      * @param sender The PendingIntent sender.
      * @param intent The fillIn intent to patch over the sender's base intent.
@@ -723,6 +740,29 @@
     }
 
     /**
+     * Sets the TaskFragment {@code container} to have a companion TaskFragment {@code companion}.
+     * This indicates that the organizer will remove the TaskFragment when the companion
+     * TaskFragment is removed.
+     *
+     * @param container the TaskFragment container
+     * @param companion the companion TaskFragment. If it is {@code null}, the transaction will
+     *                  reset the companion TaskFragment.
+     * @hide
+     */
+    @NonNull
+    public WindowContainerTransaction setCompanionTaskFragment(@NonNull IBinder container,
+            @Nullable IBinder companion) {
+        final HierarchyOp hierarchyOp =
+                new HierarchyOp.Builder(
+                        HierarchyOp.HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT)
+                        .setContainer(container)
+                        .setReparentContainer(companion)
+                        .build();
+        mHierarchyOps.add(hierarchyOp);
+        return this;
+    }
+
+    /**
      * Sets/removes the always on top flag for this {@code windowContainer}. See
      * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}.
      * Please note that this method is only intended to be used for a
@@ -906,12 +946,14 @@
         public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 5;
         public static final int CHANGE_FORCE_NO_PIP = 1 << 6;
         public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 7;
+        public static final int CHANGE_DRAG_RESIZING = 1 << 8;
 
         private final Configuration mConfiguration = new Configuration();
         private boolean mFocusable = true;
         private boolean mHidden = false;
         private boolean mIgnoreOrientationRequest = false;
         private boolean mForceTranslucent = false;
+        private boolean mDragResizing = false;
 
         private int mChangeMask = 0;
         private @ActivityInfo.Config int mConfigSetMask = 0;
@@ -932,6 +974,7 @@
             mHidden = in.readBoolean();
             mIgnoreOrientationRequest = in.readBoolean();
             mForceTranslucent = in.readBoolean();
+            mDragResizing = in.readBoolean();
             mChangeMask = in.readInt();
             mConfigSetMask = in.readInt();
             mWindowSetMask = in.readInt();
@@ -980,6 +1023,9 @@
             if ((other.mChangeMask & CHANGE_FORCE_TRANSLUCENT) != 0) {
                 mForceTranslucent = other.mForceTranslucent;
             }
+            if ((other.mChangeMask & CHANGE_DRAG_RESIZING) != 0) {
+                mDragResizing = other.mDragResizing;
+            }
             mChangeMask |= other.mChangeMask;
             if (other.mActivityWindowingMode >= 0) {
                 mActivityWindowingMode = other.mActivityWindowingMode;
@@ -1039,6 +1085,15 @@
             return mForceTranslucent;
         }
 
+        /** Gets the requested drag resizing state. */
+        public boolean getDragResizing() {
+            if ((mChangeMask & CHANGE_DRAG_RESIZING) == 0) {
+                throw new RuntimeException("Drag resizing not set. "
+                        + "Check CHANGE_DRAG_RESIZING first");
+            }
+            return mDragResizing;
+        }
+
         public int getChangeMask() {
             return mChangeMask;
         }
@@ -1100,6 +1155,9 @@
             if ((mChangeMask & CHANGE_FOCUSABLE) != 0) {
                 sb.append("focusable:" + mFocusable + ",");
             }
+            if ((mChangeMask & CHANGE_DRAG_RESIZING) != 0) {
+                sb.append("dragResizing:" + mDragResizing + ",");
+            }
             if (mBoundsChangeTransaction != null) {
                 sb.append("hasBoundsTransaction,");
             }
@@ -1117,6 +1175,7 @@
             dest.writeBoolean(mHidden);
             dest.writeBoolean(mIgnoreOrientationRequest);
             dest.writeBoolean(mForceTranslucent);
+            dest.writeBoolean(mDragResizing);
             dest.writeInt(mChangeMask);
             dest.writeInt(mConfigSetMask);
             dest.writeInt(mWindowSetMask);
@@ -1181,6 +1240,7 @@
         public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19;
         public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 20;
         public static final int HIERARCHY_OP_TYPE_FINISH_ACTIVITY = 21;
+        public static final int HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT = 22;
 
         // The following key(s) are for use with mLaunchOptions:
         // When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1395,6 +1455,11 @@
         }
 
         @NonNull
+        public IBinder getCompanionContainer() {
+            return mReparent;
+        }
+
+        @NonNull
         public IBinder getCallingActivity() {
             return mReparent;
         }
@@ -1504,6 +1569,9 @@
                     return "{RemoveTask: task=" + mContainer + "}";
                 case HIERARCHY_OP_TYPE_FINISH_ACTIVITY:
                     return "{finishActivity: activity=" + mContainer + "}";
+                case HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT:
+                    return "{setCompanionTaskFragment: container = " + mContainer + " companion = "
+                            + mReparent + "}";
                 default:
                     return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
                             + " mToTop=" + mToTop
diff --git a/core/java/android/window/WindowProvider.java b/core/java/android/window/WindowProvider.java
index b078b93..dbdc68f 100644
--- a/core/java/android/window/WindowProvider.java
+++ b/core/java/android/window/WindowProvider.java
@@ -15,8 +15,10 @@
  */
 package android.window;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.view.WindowManager.LayoutParams.WindowType;
 
 /**
@@ -36,4 +38,11 @@
     /** Gets the launch options of this provider */
     @Nullable
     Bundle getWindowContextOptions();
+
+    /**
+     * Gets the WindowContextToken of this provider.
+     * @see android.content.Context#getWindowContextToken
+     */
+    @NonNull
+    IBinder getWindowContextToken();
 }
diff --git a/core/java/android/window/WindowProviderService.java b/core/java/android/window/WindowProviderService.java
index 2d2c8de..fdc3e5a 100644
--- a/core/java/android/window/WindowProviderService.java
+++ b/core/java/android/window/WindowProviderService.java
@@ -27,7 +27,10 @@
 import android.app.ActivityThread;
 import android.app.LoadedApk;
 import android.app.Service;
+import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacksController;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -54,6 +57,8 @@
     private final WindowContextController mController = new WindowContextController(mWindowToken);
     private WindowManager mWindowManager;
     private boolean mInitialized;
+    private final ComponentCallbacksController mCallbacksController =
+            new ComponentCallbacksController();
 
     /**
      * Returns {@code true} if the {@code windowContextOptions} declares that it is a
@@ -118,6 +123,48 @@
         return mOptions;
     }
 
+    @SuppressLint({"OnNameExpected", "ExecutorRegistration"})
+    // Suppress lint because this is a legacy named function and doesn't have an optional param
+    // for executor.
+    // TODO(b/259347943): Update documentation for U.
+    /**
+     * Here we override to prevent WindowProviderService from invoking
+     * {@link Application.registerComponentCallback}, which will result in callback registered
+     * for process-level Configuration change updates.
+     */
+    @Override
+    public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
+        // For broadcasting Configuration Changes.
+        mCallbacksController.registerCallbacks(callback);
+    }
+
+    @SuppressLint("OnNameExpected")
+    @Override
+    public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
+        mCallbacksController.unregisterCallbacks(callback);
+    }
+
+    @SuppressLint("OnNameExpected")
+    @Override
+    public void onConfigurationChanged(@Nullable Configuration configuration) {
+        // This is only called from WindowTokenClient.
+        mCallbacksController.dispatchConfigurationChanged(configuration);
+    }
+
+    /**
+     * Override {@link Service}'s empty implementation and listen to {@link ActivityThread} for
+     * low memory and trim memory events.
+     */
+    @Override
+    public void onLowMemory() {
+        mCallbacksController.dispatchLowMemory();
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+        mCallbacksController.dispatchTrimMemory(level);
+    }
+
     /**
      * Returns the display ID to launch this {@link WindowProviderService}.
      *
@@ -181,5 +228,6 @@
     public void onDestroy() {
         super.onDestroy();
         mController.detachIfNeeded();
+        mCallbacksController.clearCallbacks();
     }
 }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a352063..f998a69 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2402,7 +2402,7 @@
             return;
         }
         final ThreadedRenderer renderer = getThreadedRenderer();
-        if (renderer != null) {
+        if (renderer != null && !CAPTION_ON_SHELL) {
             loadBackgroundDrawablesIfNeeded();
             WindowInsets rootInsets = getRootWindowInsets();
             mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 21bbac0..c8b85c3 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1176,6 +1176,11 @@
   closedir(dir);
 }
 
+static bool is_sdk_sandbox_uid(uid_t uid) {
+    appid_t appId = multiuser_get_app_id(uid);
+    return appId >= AID_SDK_SANDBOX_PROCESS_START && appId <= AID_SDK_SANDBOX_PROCESS_END;
+}
+
 /**
  * Make other apps data directory not visible in CE, DE storage.
  *
@@ -1262,68 +1267,77 @@
   }
   closedir(dir);
 
-  // Prepare default dirs for user 0 as user 0 always exists.
-  int result = symlink("/data/data", "/data/user/0");
-  if (result != 0) {
-    fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
-  }
-  PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION,
-      AID_ROOT, AID_ROOT, fail_fn);
-
-  for (int i = 0; i < size; i += 3) {
-    std::string const & packageName = merged_data_info_list[i];
-    std::string const & volUuid  = merged_data_info_list[i + 1];
-    std::string const & inode = merged_data_info_list[i + 2];
-
-    std::string::size_type sz;
-    long long ceDataInode = std::stoll(inode, &sz);
-
-    std::string actualCePath, actualDePath;
-    if (volUuid.compare("null") != 0) {
-      // Volume that is stored in /mnt/expand
-      char volPath[PATH_MAX];
-      char volCePath[PATH_MAX];
-      char volDePath[PATH_MAX];
-      char volCeUserPath[PATH_MAX];
-      char volDeUserPath[PATH_MAX];
-
-      snprintf(volPath, PATH_MAX, "/mnt/expand/%s", volUuid.c_str());
-      snprintf(volCePath, PATH_MAX, "%s/user", volPath);
-      snprintf(volDePath, PATH_MAX, "%s/user_de", volPath);
-      snprintf(volCeUserPath, PATH_MAX, "%s/%d", volCePath, userId);
-      snprintf(volDeUserPath, PATH_MAX, "%s/%d", volDePath, userId);
-
-      PrepareDirIfNotPresent(volPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
-      PrepareDirIfNotPresent(volCePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
-      PrepareDirIfNotPresent(volDePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
-      PrepareDirIfNotPresent(volCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
-          fail_fn);
-      PrepareDirIfNotPresent(volDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
-          fail_fn);
-
-      actualCePath = volCeUserPath;
-      actualDePath = volDeUserPath;
-    } else {
-      // Internal volume that stored in /data
-      char internalCeUserPath[PATH_MAX];
-      char internalDeUserPath[PATH_MAX];
-      snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
-      snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
-      // If it's not user 0, create /data/user/$USER.
-      if (userId == 0) {
-        actualCePath = internalLegacyCePath;
-      } else {
-        PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
-            AID_ROOT, AID_ROOT, fail_fn);
-        actualCePath = internalCeUserPath;
+  // No bind mounting of app data should occur in the case of a sandbox process since SDK sandboxes
+  // should not be able to read app data. Tmpfs was mounted however since a sandbox should not have
+  // access to app data.
+  if (!is_sdk_sandbox_uid(uid)) {
+      // Prepare default dirs for user 0 as user 0 always exists.
+      int result = symlink("/data/data", "/data/user/0");
+      if (result != 0) {
+          fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
       }
-      PrepareDirIfNotPresent(internalDeUserPath, DEFAULT_DATA_DIR_PERMISSION,
-          AID_ROOT, AID_ROOT, fail_fn);
-      actualDePath = internalDeUserPath;
-    }
-    isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode,
-        actualCePath, actualDePath, fail_fn);
+      PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                             fail_fn);
+
+      for (int i = 0; i < size; i += 3) {
+          std::string const& packageName = merged_data_info_list[i];
+          std::string const& volUuid = merged_data_info_list[i + 1];
+          std::string const& inode = merged_data_info_list[i + 2];
+
+          std::string::size_type sz;
+          long long ceDataInode = std::stoll(inode, &sz);
+
+          std::string actualCePath, actualDePath;
+          if (volUuid.compare("null") != 0) {
+              // Volume that is stored in /mnt/expand
+              char volPath[PATH_MAX];
+              char volCePath[PATH_MAX];
+              char volDePath[PATH_MAX];
+              char volCeUserPath[PATH_MAX];
+              char volDeUserPath[PATH_MAX];
+
+              snprintf(volPath, PATH_MAX, "/mnt/expand/%s", volUuid.c_str());
+              snprintf(volCePath, PATH_MAX, "%s/user", volPath);
+              snprintf(volDePath, PATH_MAX, "%s/user_de", volPath);
+              snprintf(volCeUserPath, PATH_MAX, "%s/%d", volCePath, userId);
+              snprintf(volDeUserPath, PATH_MAX, "%s/%d", volDePath, userId);
+
+              PrepareDirIfNotPresent(volPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                                     fail_fn);
+              PrepareDirIfNotPresent(volCePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                                     fail_fn);
+              PrepareDirIfNotPresent(volDePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                                     fail_fn);
+              PrepareDirIfNotPresent(volCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                                     fail_fn);
+              PrepareDirIfNotPresent(volDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+                                     fail_fn);
+
+              actualCePath = volCeUserPath;
+              actualDePath = volDeUserPath;
+          } else {
+              // Internal volume that stored in /data
+              char internalCeUserPath[PATH_MAX];
+              char internalDeUserPath[PATH_MAX];
+              snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
+              snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
+              // If it's not user 0, create /data/user/$USER.
+              if (userId == 0) {
+                  actualCePath = internalLegacyCePath;
+              } else {
+                  PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT,
+                                         AID_ROOT, fail_fn);
+                  actualCePath = internalCeUserPath;
+              }
+              PrepareDirIfNotPresent(internalDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT,
+                                     AID_ROOT, fail_fn);
+              actualDePath = internalDeUserPath;
+          }
+          isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode, actualCePath,
+                                   actualDePath, fail_fn);
+      }
   }
+
   // We set the label AFTER everything is done, as we are applying
   // the file operations on tmpfs. If we set the label when we mount
   // tmpfs, SELinux will not happy as we are changing system_data_files.
@@ -1363,6 +1377,167 @@
   freecon(dataDataContext);
 }
 
+/**
+ * Without sdk sandbox data isolation, the sandbox could detect if another app is installed on the
+ * system by "touching" other data directories like /data/misc_ce/0/sdksandbox/com.whatsapp, similar
+ * to apps without app data isolation (see {@link #isolateAppData()}).
+ *
+ * To prevent this, tmpfs is mounted onto misc_ce and misc_de directories on all possible volumes in
+ * a separate mount namespace. The sandbox directory path is then created containing the name of the
+ * client app package associated with the sdk sandbox. The contents for this (sdk level storage and
+ * shared sdk storage) are bind mounted from the sandbox data mirror.
+ */
+static void isolateSdkSandboxData(JNIEnv* env, jobjectArray pkg_data_info_list, uid_t uid,
+                                  const char* process_name, jstring managed_nice_name,
+                                  fail_fn_t fail_fn) {
+    const userid_t userId = multiuser_get_user_id(uid);
+
+    int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+    // The sandbox should only have information of one associated client app (package, uuid, inode)
+    if (size != 3) {
+        fail_fn(CREATE_ERROR(
+                "Unable to isolate sandbox data, incorrect associated app information"));
+    }
+
+    auto extract_fn = [env, process_name, managed_nice_name,
+                       pkg_data_info_list](int info_list_idx) {
+        jstring jstr = (jstring)(env->GetObjectArrayElement(pkg_data_info_list, info_list_idx));
+        return ExtractJString(env, process_name, managed_nice_name, jstr).value();
+    };
+    std::string packageName = extract_fn(0);
+    std::string volUuid = extract_fn(1);
+
+    char internalCePath[PATH_MAX];
+    char internalDePath[PATH_MAX];
+    char externalPrivateMountPath[PATH_MAX];
+    snprintf(internalCePath, PATH_MAX, "/data/misc_ce");
+    snprintf(internalDePath, PATH_MAX, "/data/misc_de");
+    snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
+
+    char ceUserPath[PATH_MAX];
+    char deUserPath[PATH_MAX];
+    if (volUuid != "null") {
+        snprintf(ceUserPath, PATH_MAX, "%s/%s/misc_ce/%d", externalPrivateMountPath,
+                 volUuid.c_str(), userId);
+        snprintf(deUserPath, PATH_MAX, "%s/%s/misc_de/%d", externalPrivateMountPath,
+                 volUuid.c_str(), userId);
+    } else {
+        snprintf(ceUserPath, PATH_MAX, "%s/%d", internalCePath, userId);
+        snprintf(deUserPath, PATH_MAX, "%s/%d", internalDePath, userId);
+    }
+
+    char ceSandboxPath[PATH_MAX];
+    char deSandboxPath[PATH_MAX];
+    snprintf(ceSandboxPath, PATH_MAX, "%s/sdksandbox", ceUserPath);
+    snprintf(deSandboxPath, PATH_MAX, "%s/sdksandbox", deUserPath);
+
+    // If the client app using the sandbox has been installed when the device is locked and the
+    // sandbox starts up when the device is locked, sandbox storage might not have been created.
+    // In that case, mount tmpfs for data isolation, but don't bind mount.
+    bool bindMountCeSandboxDataDirs = true;
+    bool bindMountDeSandboxDataDirs = true;
+    if (access(ceSandboxPath, F_OK) != 0) {
+        bindMountCeSandboxDataDirs = false;
+    }
+    if (access(deSandboxPath, F_OK) != 0) {
+        bindMountDeSandboxDataDirs = false;
+    }
+
+    char* context = nullptr;
+    char* userContext = nullptr;
+    char* sandboxContext = nullptr;
+    if (getfilecon(internalDePath, &context) < 0) {
+        fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath, strerror(errno)));
+    }
+    if (bindMountDeSandboxDataDirs) {
+        if (getfilecon(deUserPath, &userContext) < 0) {
+            fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", deUserPath, strerror(errno)));
+        }
+        if (getfilecon(deSandboxPath, &sandboxContext) < 0) {
+            fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", deSandboxPath, strerror(errno)));
+        }
+    }
+
+    MountAppDataTmpFs(internalCePath, fail_fn);
+    MountAppDataTmpFs(internalDePath, fail_fn);
+
+    // Mount tmpfs on all external volumes
+    DIR* dir = opendir(externalPrivateMountPath);
+    if (dir == nullptr) {
+        fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+    }
+    struct dirent* ent;
+    while ((ent = readdir(dir))) {
+        if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+        if (ent->d_type != DT_DIR) {
+            fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, ent->d_name));
+        }
+        auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+        auto externalCePath = StringPrintf("%s/misc_ce", volPath.c_str());
+        auto externalDePath = StringPrintf("%s/misc_de", volPath.c_str());
+
+        WaitUntilDirReady(externalCePath.c_str(), fail_fn);
+        MountAppDataTmpFs(externalCePath.c_str(), fail_fn);
+        WaitUntilDirReady(externalDePath.c_str(), fail_fn);
+        MountAppDataTmpFs(externalDePath.c_str(), fail_fn);
+    }
+    closedir(dir);
+
+    char mirrorCeSandboxPath[PATH_MAX];
+    char mirrorDeSandboxPath[PATH_MAX];
+    snprintf(mirrorCeSandboxPath, PATH_MAX, "/data_mirror/misc_ce/%s/%d/sdksandbox",
+             volUuid.c_str(), userId);
+    snprintf(mirrorDeSandboxPath, PATH_MAX, "/data_mirror/misc_de/%s/%d/sdksandbox",
+             volUuid.c_str(), userId);
+
+    if (bindMountCeSandboxDataDirs) {
+        PrepareDir(ceUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+        PrepareDir(ceSandboxPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+        // TODO(b/231322885): Use inode numbers to find the correct app path when the device locked.
+        createAndMountAppData(packageName, packageName, mirrorCeSandboxPath, ceSandboxPath, fail_fn,
+                              true /*call_fail_fn*/);
+
+        relabelDir(ceSandboxPath, sandboxContext, fail_fn);
+        relabelDir(ceUserPath, userContext, fail_fn);
+    }
+    if (bindMountDeSandboxDataDirs) {
+        PrepareDir(deUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+        PrepareDir(deSandboxPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+        createAndMountAppData(packageName, packageName, mirrorDeSandboxPath, deSandboxPath, fail_fn,
+                              true /*call_fail_fn*/);
+
+        relabelDir(deSandboxPath, sandboxContext, fail_fn);
+        relabelDir(deUserPath, userContext, fail_fn);
+    }
+
+    // We set the label AFTER everything is done, as we are applying
+    // the file operations on tmpfs. If we set the label when we mount
+    // tmpfs, SELinux will not happy as we are changing system_data_files.
+    relabelDir(internalCePath, context, fail_fn);
+    relabelDir(internalDePath, context, fail_fn);
+
+    // Relabel CE and DE dirs under /mnt/expand
+    dir = opendir(externalPrivateMountPath);
+    if (dir == nullptr) {
+        fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+    }
+    while ((ent = readdir(dir))) {
+        if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+        auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+        auto externalCePath = StringPrintf("%s/misc_ce", volPath.c_str());
+        auto externalDePath = StringPrintf("%s/misc_de", volPath.c_str());
+        relabelDir(externalCePath.c_str(), context, fail_fn);
+        relabelDir(externalDePath.c_str(), context, fail_fn);
+    }
+    closedir(dir);
+
+    if (bindMountDeSandboxDataDirs) {
+        freecon(sandboxContext);
+        freecon(userContext);
+    }
+    freecon(context);
+}
+
 static void insertPackagesToMergedList(JNIEnv* env,
   std::vector<std::string>& merged_data_info_list,
   jobjectArray data_info_list, const char* process_name,
@@ -1428,6 +1603,12 @@
   MountAppDataTmpFs(kCurProfileDirPath, fail_fn);
   MountAppDataTmpFs(kRefProfileDirPath, fail_fn);
 
+  // Sandbox processes do not have JIT profile, so no data needs to be bind mounted. However, it
+  // should still not have access to JIT profile, so tmpfs is mounted.
+  if (is_sdk_sandbox_uid(uid)) {
+      return;
+  }
+
   // Create profile directory for this user.
   std::string actualCurUserProfile = StringPrintf("%s/%d", kCurProfileDirPath, user_id);
   PrepareDir(actualCurUserProfile, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
@@ -1580,9 +1761,15 @@
     // Make sure app is running in its own mount namespace before isolating its data directories.
     ensureInAppMountNamespace(fail_fn);
 
-    // Sandbox data and jit profile directories by overlaying a tmpfs on those dirs and bind
-    // mount all related packages separately.
+    // Isolate app data, jit profile and sandbox data directories by overlaying a tmpfs on those
+    // dirs and bind mount all related packages separately.
     if (mount_data_dirs) {
+        // Sdk sandbox data isolation does not need to occur for app processes since sepolicy
+        // prevents access to sandbox data anyway.
+        if (is_sdk_sandbox_uid(uid)) {
+            isolateSdkSandboxData(env, pkg_data_info_list, uid, process_name, managed_nice_name,
+                                  fail_fn);
+        }
         isolateAppData(env, pkg_data_info_list, allowlisted_data_info_list, uid, process_name,
                        managed_nice_name, fail_fn);
         isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 07e05c6..0c707fc 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1914,6 +1914,10 @@
     -->
     <string name="config_defaultCaptivePortalLoginPackageName" translatable="false">com.android.captiveportallogin</string>
 
+    <!-- The package name of the dock manager app. Must be granted the
+         POST_NOTIFICATIONS permission. -->
+    <string name="config_defaultDockManagerPackageName" translatable="false"></string>
+
     <!-- Whether to enable geocoder overlay which allows geocoder to be replaced
          by an app at run-time. When disabled, only the
          config_geocoderProviderPackageName package will be searched for
@@ -2473,15 +2477,15 @@
     <integer name="config_dreamsBatteryLevelDrainCutoff">5</integer>
     <!-- Limit of how long the device can remain unlocked due to attention checking.  -->
     <integer name="config_attentionMaximumExtension">900000</integer> <!-- 15 minutes.  -->
-    <!-- Is the system user the only user allowed to dream. -->
-    <bool name="config_dreamsOnlyEnabledForSystemUser">false</bool>
+    <!-- Whether there is to be a chosen Dock User who is the only user allowed to dream. -->
+    <bool name="config_dreamsOnlyEnabledForDockUser">false</bool>
     <!-- Whether dreams are disabled when ambient mode is suppressed. -->
     <bool name="config_dreamsDisabledByAmbientModeSuppressionConfig">false</bool>
 
     <!-- The duration in milliseconds of the dream opening animation.  -->
     <integer name="config_dreamOpenAnimationDuration">250</integer>
     <!-- The duration in milliseconds of the dream closing animation.  -->
-    <integer name="config_dreamCloseAnimationDuration">100</integer>
+    <integer name="config_dreamCloseAnimationDuration">300</integer>
 
     <!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
          assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
@@ -2712,9 +2716,9 @@
          will be locked. -->
     <bool name="config_multiuserDelayUserDataLocking">false</bool>
 
-    <!-- Whether to automatically switch a non-primary user back to the primary user after a
-         timeout when the device is docked.  -->
-    <bool name="config_enableTimeoutToUserZeroWhenDocked">false</bool>
+    <!-- Whether to automatically switch to the designated Dock User (the user chosen for
+         displaying dreams, etc.) after a timeout when the device is docked.  -->
+    <bool name="config_enableTimeoutToDockUserWhenDocked">false</bool>
 
     <!-- Whether to only install system packages on a user if they're allowlisted for that user
          type. These are flags and can be freely combined.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8e7da4a..694040a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -466,7 +466,7 @@
   <java-symbol type="integer" name="config_multiuserMaximumUsers" />
   <java-symbol type="integer" name="config_multiuserMaxRunningUsers" />
   <java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
-  <java-symbol type="bool" name="config_enableTimeoutToUserZeroWhenDocked" />
+  <java-symbol type="bool" name="config_enableTimeoutToDockUserWhenDocked" />
   <java-symbol type="integer" name="config_userTypePackageWhitelistMode"/>
   <java-symbol type="xml" name="config_user_types" />
   <java-symbol type="integer" name="config_safe_media_volume_index" />
@@ -2235,7 +2235,7 @@
   <java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" />
   <java-symbol type="string" name="config_dreamsDefaultComponent" />
   <java-symbol type="bool" name="config_dreamsDisabledByAmbientModeSuppressionConfig" />
-  <java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" />
+  <java-symbol type="bool" name="config_dreamsOnlyEnabledForDockUser" />
   <java-symbol type="integer" name="config_dreamOpenAnimationDuration" />
   <java-symbol type="integer" name="config_dreamCloseAnimationDuration" />
   <java-symbol type="array" name="config_supportedDreamComplications" />
@@ -3466,6 +3466,9 @@
   <!-- Captive Portal Login -->
   <java-symbol type="string" name="config_defaultCaptivePortalLoginPackageName" />
 
+  <!-- Dock Manager -->
+  <java-symbol type="string" name="config_defaultDockManagerPackageName" />
+
   <!-- Optional IPsec algorithms -->
   <java-symbol type="array" name="config_optionalIpSecAlgorithms" />
 
diff --git a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
index 98485c0..ee73f00 100644
--- a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
+++ b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
@@ -29,10 +29,11 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 /**
- * Test class for {@link ConstrainDisplayApisConfig}.
+ * Test for {@link ConstrainDisplayApisConfig}.
  *
  * Build/Install/Run:
  * atest FrameworksCoreTests:ConstrainDisplayApisConfigTest
@@ -72,6 +73,7 @@
         testNeverConstrainDisplayApis("com.android.test", /* version= */ 1, /* expected= */ false);
     }
 
+    @Ignore("b/257375674")
     @Test
     public void neverConstrainDisplayApis_flagsHasSingleEntry_returnsTrueForPackageWithinRange() {
         setNeverConstrainDisplayApisFlag("com.android.test:1:1");
@@ -107,6 +109,7 @@
         testNeverConstrainDisplayApis("com.android.test4", /* version= */ 9, /* expected= */ false);
     }
 
+    @Ignore("b/257375674")
     @Test
     public void neverConstrainDisplayApis_flagHasInvalidEntries_ignoresInvalidEntries() {
         // We add a valid entry before and after the invalid ones to make sure they are applied.
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index 7ebebc9..c59a3f5 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -246,10 +246,12 @@
     @Test
     public void getQFactorAndResonantFrequency_differentValues_returnsNaN() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setQFactor(1f)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null))
                 .build();
         VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setQFactor(2f)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 2, 2, null))
                 .build();
@@ -258,6 +260,7 @@
 
         assertTrue(Float.isNaN(info.getQFactor()));
         assertTrue(Float.isNaN(info.getResonantFrequencyHz()));
+        assertEmptyFrequencyProfileAndControl(info);
 
         // One vibrator with values undefined.
         VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 3).build();
@@ -266,16 +269,19 @@
 
         assertTrue(Float.isNaN(info.getQFactor()));
         assertTrue(Float.isNaN(info.getResonantFrequencyHz()));
+        assertEmptyFrequencyProfileAndControl(info);
     }
 
     @Test
     public void getQFactorAndResonantFrequency_sameValues_returnsValue() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setQFactor(10f)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(
                         /* resonantFrequencyHz= */ 11, 10, 0.5f, null))
                 .build();
         VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setQFactor(10f)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(
                         /* resonantFrequencyHz= */ 11, 5, 1, null))
@@ -285,113 +291,131 @@
 
         assertEquals(10f, info.getQFactor(), TEST_TOLERANCE);
         assertEquals(11f, info.getResonantFrequencyHz(), TEST_TOLERANCE);
+
+        // No frequency range defined.
+        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL));
     }
 
     @Test
     public void getFrequencyProfile_noVibrator_returnsEmpty() {
         VibratorInfo info = new SystemVibrator.NoVibratorInfo();
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
     }
 
     @Test
     public void getFrequencyProfile_differentResonantFrequencyOrResolutionValues_returnsEmpty() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1,
                         new float[] { 0, 1 }))
                 .build();
         VibratorInfo differentResonantFrequency = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 1, 1,
                         new float[] { 0, 1 }))
                 .build();
         VibratorInfo info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, differentResonantFrequency});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
 
         VibratorInfo differentFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 2,
                         new float[] { 0, 1 }))
                 .build();
         info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, differentFrequencyResolution});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
     }
 
     @Test
     public void getFrequencyProfile_missingValues_returnsEmpty() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1,
                         new float[] { 0, 1 }))
                 .build();
         VibratorInfo missingResonantFrequency = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(Float.NaN, 1, 1,
                         new float[] { 0, 1 }))
                 .build();
         VibratorInfo info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, missingResonantFrequency});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
 
         VibratorInfo missingMinFrequency = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, Float.NaN, 1,
                         new float[] { 0, 1 }))
                 .build();
         info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, missingMinFrequency});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
 
         VibratorInfo missingFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, Float.NaN,
                         new float[] { 0, 1 }))
                 .build();
         info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, missingFrequencyResolution});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
 
         VibratorInfo missingMaxAmplitudes = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null))
                 .build();
         info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, missingMaxAmplitudes});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
     }
 
     @Test
     public void getFrequencyProfile_unalignedMaxAmplitudes_returnsEmpty() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f,
                         new float[] { 0, 1, 1, 0 }))
                 .build();
         VibratorInfo unalignedMinFrequency = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.1f, 0.5f,
                         new float[] { 0, 1, 1, 0 }))
                 .build();
         VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f,
                         new float[] { 0, 1, 1, 0 }))
                 .build();
         VibratorInfo info = new SystemVibrator.MultiVibratorInfo(
                 new VibratorInfo[]{firstVibrator, unalignedMinFrequency, thirdVibrator});
 
-        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEmptyFrequencyProfileAndControl(info);
     }
 
     @Test
     public void getFrequencyProfile_alignedProfiles_returnsIntersection() {
         VibratorInfo firstVibrator = new VibratorInfo.Builder(/* id= */ 1)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f,
                         new float[] { 0.5f, 1, 1, 0.5f }))
                 .build();
         VibratorInfo secondVibrator = new VibratorInfo.Builder(/* id= */ 2)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f,
                         new float[] { 1, 1, 1 }))
                 .build();
         VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 3)
+                .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
                 .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f,
                         new float[] { 0.8f, 1, 0.8f, 0.5f }))
                 .build();
@@ -401,6 +425,20 @@
         assertEquals(
                 new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }),
                 info.getFrequencyProfile());
+        assertEquals(true, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL));
+
+        // Third vibrator without frequency control capability.
+        thirdVibrator = new VibratorInfo.Builder(/* id= */ 3)
+                .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f,
+                        new float[] { 0.8f, 1, 0.8f, 0.5f }))
+                .build();
+        info = new SystemVibrator.MultiVibratorInfo(
+                new VibratorInfo[]{firstVibrator, secondVibrator, thirdVibrator});
+
+        assertEquals(
+                new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }),
+                info.getFrequencyProfile());
+        assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL));
     }
 
     @Test
@@ -547,4 +585,12 @@
         VibrationAttributes vibrationAttributes = captor.getValue();
         assertEquals(new VibrationAttributes.Builder().build(), vibrationAttributes);
     }
+
+    /**
+     * Asserts that the frequency profile is empty, and therefore frequency control isn't supported.
+     */
+    void assertEmptyFrequencyProfileAndControl(VibratorInfo info) {
+        assertTrue(info.getFrequencyProfile().isEmpty());
+        assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL));
+    }
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index abf7e99..42c892a 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1667,6 +1667,9 @@
      * effectively treating them as zeros. In API level {@value Build.VERSION_CODES#P} and above
      * these parameters will be respected.
      *
+     * <p>Note: antialiasing is not supported, therefore {@link Paint#ANTI_ALIAS_FLAG} is
+     * ignored.</p>
+     *
      * @param bitmap The bitmap to draw using the mesh
      * @param meshWidth The number of columns in the mesh. Nothing is drawn if this is 0
      * @param meshHeight The number of rows in the mesh. Nothing is drawn if this is 0
@@ -1678,7 +1681,7 @@
      *            null, there must be at least (meshWidth+1) * (meshHeight+1) + colorOffset values
      *            in the array.
      * @param colorOffset Number of color elements to skip before drawing
-     * @param paint May be null. The paint used to draw the bitmap
+     * @param paint May be null. The paint used to draw the bitmap. Antialiasing is not supported.
      */
     public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
             @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
@@ -1832,9 +1835,12 @@
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patch.)
      *
+     * <p>Note: antialiasing is not supported, therefore {@link Paint#ANTI_ALIAS_FLAG} is
+     * ignored.</p>
+     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
-     * @param paint The paint to draw the bitmap with. may be null
+     * @param paint The paint to draw the bitmap with. May be null. Antialiasing is not supported.
      */
     public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
         super.drawPatch(patch, dst, paint);
@@ -1843,9 +1849,12 @@
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patch.)
      *
+     * <p>Note: antialiasing is not supported, therefore {@link Paint#ANTI_ALIAS_FLAG} is
+     * ignored.</p>
+     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
-     * @param paint The paint to draw the bitmap with. may be null
+     * @param paint The paint to draw the bitmap with. May be null. Antialiasing is not supported.
      */
     public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
         super.drawPatch(patch, dst, paint);
@@ -2278,6 +2287,9 @@
      * array is optional, but if it is present, then it is used to specify the index of each
      * triangle, rather than just walking through the arrays in order.
      *
+     * <p>Note: antialiasing is not supported, therefore {@link Paint#ANTI_ALIAS_FLAG} is
+     * ignored.</p>
+     *
      * @param mode How to interpret the array of vertices
      * @param vertexCount The number of values in the vertices array (and corresponding texs and
      *            colors arrays if non-null). Each logical vertex is two values (x, y), vertexCount
@@ -2292,8 +2304,9 @@
      * @param colorOffset Number of values in colors to skip before drawing.
      * @param indices If not null, array of indices to reference into the vertex (texs, colors)
      *            array.
-     * @param indexCount number of entries in the indices array (if not null).
-     * @param paint Specifies the shader to use if the texs array is non-null.
+     * @param indexCount Number of entries in the indices array (if not null).
+     * @param paint Specifies the shader to use if the texs array is non-null. Antialiasing is not
+     *            supported.
      */
     public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
             int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 451b99e..f438a03 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -137,6 +137,13 @@
      * <p>Enabling this flag will cause all draw operations that support
      * antialiasing to use it.</p>
      *
+     * <p>Notable draw operations that do <b>not</b> support antialiasing include:</p>
+     * <ul>
+     *      <li>{@link android.graphics.Canvas#drawBitmapMesh}</li>
+     *      <li>{@link android.graphics.Canvas#drawPatch}</li>
+     *      <li>{@link android.graphics.Canvas#drawVertices}</li>
+     * </ul>
+     *
      * @see #Paint(int)
      * @see #setFlags(int)
      */
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 74303e2..9d841ea 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -18,6 +18,12 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
+import static androidx.window.extensions.embedding.SplitContainer.getFinishPrimaryWithSecondaryBehavior;
+import static androidx.window.extensions.embedding.SplitContainer.getFinishSecondaryWithPrimaryBehavior;
+import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
+import static androidx.window.extensions.embedding.SplitContainer.shouldFinishPrimaryWithSecondary;
+import static androidx.window.extensions.embedding.SplitContainer.shouldFinishSecondaryWithPrimary;
+
 import android.app.Activity;
 import android.app.WindowConfiguration.WindowingMode;
 import android.content.Intent;
@@ -140,6 +146,8 @@
 
         // Set adjacent to each other so that the containers below will be invisible.
         setAdjacentTaskFragments(wct, launchingFragmentToken, secondaryFragmentToken, rule);
+        setCompanionTaskFragment(wct, launchingFragmentToken, secondaryFragmentToken, rule,
+                false /* isStacked */);
     }
 
     /**
@@ -215,6 +223,28 @@
         wct.setAdjacentTaskFragments(primary, secondary, adjacentParams);
     }
 
+    void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder primary, @NonNull IBinder secondary, @NonNull SplitRule splitRule,
+            boolean isStacked) {
+        final boolean finishPrimaryWithSecondary;
+        if (isStacked) {
+            finishPrimaryWithSecondary = shouldFinishAssociatedContainerWhenStacked(
+                    getFinishPrimaryWithSecondaryBehavior(splitRule));
+        } else {
+            finishPrimaryWithSecondary = shouldFinishPrimaryWithSecondary(splitRule);
+        }
+        wct.setCompanionTaskFragment(primary, finishPrimaryWithSecondary ? secondary : null);
+
+        final boolean finishSecondaryWithPrimary;
+        if (isStacked) {
+            finishSecondaryWithPrimary = shouldFinishAssociatedContainerWhenStacked(
+                    getFinishSecondaryWithPrimaryBehavior(splitRule));
+        } else {
+            finishSecondaryWithPrimary = shouldFinishSecondaryWithPrimary(splitRule);
+        }
+        wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
+    }
+
     TaskFragmentCreationParams createFragmentOptions(@NonNull IBinder fragmentToken,
             @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
         if (mFragmentInfos.containsKey(fragmentToken)) {
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 16760e26..d52caaf 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -389,6 +389,10 @@
                 // launching activity in the Task.
                 mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
                 mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
+            } else if (taskFragmentInfo.isClearedForReorderActivityToFront()) {
+                // Do not finish the dependents if this TaskFragment was cleared to reorder
+                // the launching Activity to front of the Task.
+                mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
             } else if (!container.isWaitingActivityAppear()) {
                 // Do not finish the container before the expected activity appear until
                 // timeout.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 362f1fa..cb470ba 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -371,13 +371,16 @@
             @NonNull SplitAttributes splitAttributes) {
         // Clear adjacent TaskFragments if the container is shown in fullscreen, or the
         // secondaryContainer could not be finished.
-        if (!shouldShowSplit(splitAttributes)) {
+        boolean isStacked = !shouldShowSplit(splitAttributes);
+        if (isStacked) {
             setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                     null /* secondary */, null /* splitRule */);
         } else {
             setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                     secondaryContainer.getTaskFragmentToken(), splitRule);
         }
+        setCompanionTaskFragment(wct, primaryContainer.getTaskFragmentToken(),
+                secondaryContainer.getTaskFragmentToken(), splitRule, isStacked);
     }
 
     /**
@@ -489,8 +492,15 @@
                     || splitContainer.getSecondaryContainer().getInfo() == null) {
                 return RESULT_EXPAND_FAILED_NO_TF_INFO;
             }
-            expandTaskFragment(wct, splitContainer.getPrimaryContainer().getTaskFragmentToken());
-            expandTaskFragment(wct, splitContainer.getSecondaryContainer().getTaskFragmentToken());
+            final IBinder primaryToken =
+                    splitContainer.getPrimaryContainer().getTaskFragmentToken();
+            final IBinder secondaryToken =
+                    splitContainer.getSecondaryContainer().getTaskFragmentToken();
+            expandTaskFragment(wct, primaryToken);
+            expandTaskFragment(wct, secondaryToken);
+            // Set the companion TaskFragment when the two containers stacked.
+            setCompanionTaskFragment(wct, primaryToken, secondaryToken,
+                    splitContainer.getSplitRule(), true /* isStacked */);
             return RESULT_EXPANDED;
         }
         return RESULT_NOT_EXPANDED;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index b516e140..2192b5c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -36,6 +36,7 @@
 import android.os.IBinder;
 import android.util.ArrayMap;
 import android.window.WindowContext;
+import android.window.WindowProvider;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -71,7 +72,7 @@
 
     private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>();
 
-    private final Map<IBinder, WindowContextConfigListener> mWindowContextConfigListeners =
+    private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
             new ArrayMap<>();
 
     public WindowLayoutComponentImpl(@NonNull Context context) {
@@ -121,21 +122,21 @@
         }
         if (!context.isUiContext()) {
             throw new IllegalArgumentException("Context must be a UI Context, which should be"
-                    + " an Activity or a WindowContext");
+                    + " an Activity, WindowContext or InputMethodService");
         }
         mFoldingFeatureProducer.getData((features) -> {
-            // Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
             WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
             consumer.accept(newWindowLayout);
         });
         mWindowLayoutChangeListeners.put(context, consumer);
 
-        if (context instanceof WindowContext) {
+        // TODO(b/258065175) Further extend this to ContextWrappers.
+        if (context instanceof WindowProvider) {
             final IBinder windowContextToken = context.getWindowContextToken();
-            final WindowContextConfigListener listener =
-                    new WindowContextConfigListener(windowContextToken);
+            final ConfigurationChangeListener listener =
+                    new ConfigurationChangeListener(windowContextToken);
             context.registerComponentCallbacks(listener);
-            mWindowContextConfigListeners.put(windowContextToken, listener);
+            mConfigurationChangeListeners.put(windowContextToken, listener);
         }
     }
 
@@ -150,10 +151,10 @@
             if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
                 continue;
             }
-            if (context instanceof WindowContext) {
+            if (context instanceof WindowProvider) {
                 final IBinder token = context.getWindowContextToken();
-                context.unregisterComponentCallbacks(mWindowContextConfigListeners.get(token));
-                mWindowContextConfigListeners.remove(token);
+                context.unregisterComponentCallbacks(mConfigurationChangeListeners.get(token));
+                mConfigurationChangeListeners.remove(token);
             }
             break;
         }
@@ -349,10 +350,10 @@
         }
     }
 
-    private final class WindowContextConfigListener implements ComponentCallbacks {
+    private final class ConfigurationChangeListener implements ComponentCallbacks {
         final IBinder mToken;
 
-        WindowContextConfigListener(IBinder token) {
+        ConfigurationChangeListener(IBinder token) {
             mToken = token;
         }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 40f7a27..92011af 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -169,6 +169,7 @@
                 new Point(),
                 false /* isTaskClearedForReuse */,
                 false /* isTaskFragmentClearedForPip */,
+                false /* isClearedForReorderActivityToFront */,
                 new Point());
     }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index 957a248..79813c7 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -144,6 +144,6 @@
                 mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
                 false /* isVisible */, new ArrayList<>(), new Point(),
                 false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
-                new Point());
+                false /* isClearedForReorderActivityToFront */, new Point());
     }
 }
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index f85103e..08420fe 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string>
     <string name="handle_text" msgid="1766582106752184456">"መያዣ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገጽ"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 5eda65f..ae590a9 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
     <string name="back_button_text" msgid="1469718707134137085">"رجوع"</string>
     <string name="handle_text" msgid="1766582106752184456">"مقبض"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"تقسيم الشاشة"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"المزيد"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"نافذة عائمة"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 5a2e6cd..0e58460 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
     <string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string>
     <string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"বিভাজিত স্ক্ৰীন"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"অধিক"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ওপঙা"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 06539a1..954b120 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string>
     <string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Ardı"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Üzən pəncərə"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index c91473e..aa68a5b 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
     <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Podeljeni ekran"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Još"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 9d0cd77..878175c7 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
     <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Падзяліць экран"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Яшчэ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Зрабіць рухомым акном"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 230f71d..0f614f9 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
     <string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Разделяне на екрана"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Още"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Плаващо"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 71a2fc2..4702586 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string>
     <string name="handle_text" msgid="1766582106752184456">"হাতল"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"স্প্লিট স্ক্রিন"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"আরও"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ফ্লোট"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 29e83b4..77e99fe 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -86,9 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
     <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
-    <string name="fullscreen_text" msgid="1162316685217676079">"Puni zaslon"</string>
-    <string name="desktop_text" msgid="1077633567027630454">"Stolni način rada"</string>
-    <string name="split_screen_text" msgid="1396336058129570886">"Razdvojeni zaslon"</string>
+    <string name="fullscreen_text" msgid="1162316685217676079">"Cijeli ekran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Način rada radne površine"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Podijeljeni ekran"</string>
     <string name="more_button_text" msgid="3655388105592893530">"Više"</string>
-    <string name="float_button_text" msgid="9221657008391364581">"Plutajući"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Lebdeći"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 29ce75e..033b3b78 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Enrere"</string>
     <string name="handle_text" msgid="1766582106752184456">"Ansa"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Més"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flotant"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index 7c7cf40..0e5f952 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Zpět"</string>
     <string name="handle_text" msgid="1766582106752184456">"Úchyt"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Rozdělená obrazovka"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Více"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Plovoucí"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 0f5b701..44e561d 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string>
     <string name="handle_text" msgid="1766582106752184456">"Håndtag"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Opdelt skærm"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Mere"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Svævende"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 10f8836..d271f61 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Zurück"</string>
     <string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Geteilter Bildschirm"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Mehr"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 9630352..f53ea9e 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string>
     <string name="handle_text" msgid="1766582106752184456">"Λαβή"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Διαχωρισμός οθόνης"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Περισσότερα"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Κινούμενο"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index f714ca2..6ed6584 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -35,7 +35,7 @@
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
     <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
     <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
-    <string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string>
+    <string name="accessibility_divider" msgid="703810061635792791">"Split-screen divider"</string>
     <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string>
     <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string>
     <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string>
@@ -64,9 +64,9 @@
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
-    <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Control bubbles at any time"</string>
+    <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Control bubbles anytime"</string>
     <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tap Manage to turn off bubbles from this app"</string>
-    <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
+    <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Got it"</string>
     <string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No recent bubbles"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recent bubbles and dismissed bubbles will appear here"</string>
     <string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
@@ -81,14 +81,14 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expand for more information."</string>
-    <string name="maximize_button_text" msgid="1650859196290301963">"Maximise"</string>
-    <string name="minimize_button_text" msgid="271592547935841753">"Minimise"</string>
+    <string name="maximize_button_text" msgid="1650859196290301963">"Maximize"</string>
+    <string name="minimize_button_text" msgid="271592547935841753">"Minimize"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Close"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Back"</string>
     <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
-    <string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
-    <string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
-    <string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
+    <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
     <string name="more_button_text" msgid="3655388105592893530">"More"</string>
     <string name="float_button_text" msgid="9221657008391364581">"Float"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index aedca54..e5a6184 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
     <string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Más"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 4cbc733..b8ca91e0 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string>
     <string name="handle_text" msgid="1766582106752184456">"Käepide"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Jagatud ekraanikuva"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Rohkem"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Hõljuv"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index e3da48a..749fbd7 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Atzera"</string>
     <string name="handle_text" msgid="1766582106752184456">"Kontu-izena"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitua"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 501f366..b6a01ed 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
     <string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string>
     <string name="handle_text" msgid="1766582106752184456">"دستگیره"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"تمام‌صفحه"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"صفحهٔ دونیمه"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"بیشتر"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"شناور"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index c9b95dc..01bc9f1 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string>
     <string name="handle_text" msgid="1766582106752184456">"Kahva"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Jaettu näyttö"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Lisää"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Kelluva ikkuna"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 79b01de..76f3b62 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
     <string name="handle_text" msgid="1766582106752184456">"Identifiant"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flottant"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 0456cfb..4353c79 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
     <string name="handle_text" msgid="1766582106752184456">"Poignée"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flottante"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 7c28e4e..5bfd802 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
     <string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Máis"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index 73b2e41..2976a8a 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
     <string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string>
     <string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"સ્ક્રીનને વિભાજિત કરો"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"વધુ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ફ્લોટિંગ વિન્ડો"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index e70b15d..aa91d7d 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
     <string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string>
     <string name="handle_text" msgid="1766582106752184456">"हैंडल"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन मोड"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ज़्यादा देखें"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"फ़्लोट"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index d816c50..faa6cb9 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Vissza"</string>
     <string name="handle_text" msgid="1766582106752184456">"Fogópont"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Osztott képernyő"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Továbbiak"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Lebegő"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index e9ab5f4..b2f3c38 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Հետ"</string>
     <string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Տրոհված էկրան"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Ավելին"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Լողացող պատուհան"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index cd983f5..0bb76bb 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
     <string name="handle_text" msgid="1766582106752184456">"Tuas"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Layar Terpisah"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Lainnya"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Mengambang"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 0a20007..f3cb13d 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Til baka"</string>
     <string name="handle_text" msgid="1766582106752184456">"Handfang"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Skjáskipting"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Meira"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Reikult"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 7e232d4..d486128 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Indietro"</string>
     <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Schermo diviso"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Altro"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Mobile"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 68cf8aa..acab582 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
     <string name="back_button_text" msgid="1469718707134137085">"חזרה"</string>
     <string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"מסך מפוצל"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"עוד"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"בלונים"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 6f22e3dc..15349a2 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"閉じる"</string>
     <string name="back_button_text" msgid="1469718707134137085">"戻る"</string>
     <string name="handle_text" msgid="1766582106752184456">"ハンドル"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"分割画面"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"その他"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"フローティング"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 6989dca..b29c48e 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
     <string name="back_button_text" msgid="1469718707134137085">"უკან"</string>
     <string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"ეკრანის გაყოფა"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"სხვა"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ფარფატი"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index c83486b..151810c 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Артқа"</string>
     <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлу"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Қосымша"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Қалқыма"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index dd25f20..afe55bc 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string>
     <string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់​ពេញ"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"មុខងារ​បំបែក​អេក្រង់"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ច្រើនទៀត"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"អណ្ដែត"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 473cbe1..48c8bba 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string>
     <string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್‌ಸ್ಕ್ರೀನ್"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್‌ಟಾಪ್ ಮೋಡ್"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ಇನ್ನಷ್ಟು"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ಫ್ಲೋಟ್"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 6975095..f740076 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
     <string name="back_button_text" msgid="1469718707134137085">"뒤로"</string>
     <string name="handle_text" msgid="1766582106752184456">"핸들"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"화면 분할"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"더보기"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"플로팅"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 88d02a6..5b33fc7 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Артка"</string>
     <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлүү"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Дагы"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Калкыма"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index 58056fa..75f0fd4 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Atgal"</string>
     <string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Išskaidyto ekrano režimas"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Daugiau"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Slankusis langas"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index 30d6ef1..e3bbf78 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string>
     <string name="handle_text" msgid="1766582106752184456">"Turis"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Sadalīt ekrānu"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Vairāk"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Peldošs"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 1367c03..ab904c0 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
     <string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string>
     <string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ഡെസ്‌ക്ടോപ്പ് മോഡ്"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"സ്‌ക്രീൻ വിഭജനം"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"കൂടുതൽ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ഫ്ലോട്ട്"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 83cf9a9..43e67c2 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Буцах"</string>
     <string name="handle_text" msgid="1766582106752184456">"Бариул"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Дэлгэцийг хуваах"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Бусад"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Хөвөгч"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 380270b..a0ce393 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
     <string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string>
     <string name="handle_text" msgid="1766582106752184456">"हँडल"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"फुलस्‍क्रीन"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"आणखी"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index c85fce5..70d4f3d 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
     <string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string>
     <string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"မျက်နှာပြင် ခွဲ၍ပြသရန်"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ပိုပြပါ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"မျှောရန်"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 71608c6..649bb72 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -64,7 +64,7 @@
     <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ikke vis samtaler i bobler"</string>
     <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat med bobler"</string>
     <string name="bubbles_user_education_description" msgid="4215862563054175407">"Nye samtaler vises som flytende ikoner eller bobler. Trykk for å åpne en boble. Dra for å flytte den."</string>
-    <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Kontrollér bobler når som helst"</string>
+    <string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Kontroller bobler når som helst"</string>
     <string name="bubbles_user_education_manage" msgid="3460756219946517198">"Trykk på Administrer for å slå av bobler for denne appen"</string>
     <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Greit"</string>
     <string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ingen nylige bobler"</string>
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string>
     <string name="handle_text" msgid="1766582106752184456">"Håndtak"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Delt skjerm"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Svevende"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 28b64c2..976f401 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
     <string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string>
     <string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रिन"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"थप"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index b0bc07b..3dee016 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
     <string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Gesplitst scherm"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Zwevend"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index c0a2b81..b5e87c4 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string>
     <string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ଅଧିକ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ଫ୍ଲୋଟ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 5cdaeaf..8e0f103 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string>
     <string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"ਹੋਰ"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ਫ਼ਲੋਟ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index af65b76..69ea2ea 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string>
     <string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Podzielony ekran"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Więcej"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Pływające"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 68bfda4..d8058f8 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Închide"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Înapoi"</string>
     <string name="handle_text" msgid="1766582106752184456">"Ghidaj"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Ecran împărțit"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Mai multe"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Flotantă"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index a0512b8..f6bfb53 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
     <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Разделить экран"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Ещё"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Плавающее окно"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index a8d4fe5..4504500 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
     <string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string>
     <string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්‍රකාරය"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"බෙදුම් තිරය"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"තව"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"පාවෙන"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 3716f35..3ca193f 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string>
     <string name="handle_text" msgid="1766582106752184456">"Ročica"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Razdeljen zaslon"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Več"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Lebdeče"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index b5203fd..d1d215f 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Pas"</string>
     <string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Ekrani i ndarë"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Më shumë"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Pluskuese"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 20bb380..085b9e5 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
     <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Подељени екран"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Још"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 9e31581..2b7997c 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string>
     <string name="handle_text" msgid="1766582106752184456">"Handtag"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Delad skärm"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Svävande"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 1b7c651..61b6c07 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string>
     <string name="handle_text" msgid="1766582106752184456">"Ncha"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Gawa Skrini"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Zaidi"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Inayoelea"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 4db168e..dfc03bc 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
     <string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string>
     <string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"திரையைப் பிரிக்கும்"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"கூடுதல் விருப்பத்தேர்வுகள்"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index e677268..d13ebb6 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
     <string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string>
     <string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"డెస్క్‌టాప్ మోడ్"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"స్ప్లిట్ స్క్రీన్"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"మరిన్ని"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"ఫ్లోట్"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 8395e2a..db0f033 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Isara"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Bumalik"</string>
     <string name="handle_text" msgid="1766582106752184456">"Handle"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Higit pa"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Float"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 5516a73..7b73778 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Geri"</string>
     <string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Daha Fazla"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Havada Süzülen"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 73cb70d..893e005 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
     <string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Розділити екран"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Більше"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Плаваюче вікно"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 842a255..c7c7843 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
     <string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string>
     <string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"اسپلٹ اسکرین"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"مزید"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"فلوٹ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 9f8b686..e66ccf4 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string>
     <string name="handle_text" msgid="1766582106752184456">"Xử lý"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Toàn màn hình"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Chế độ máy tính"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Chia đôi màn hình"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Tuỳ chọn khác"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Nổi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index c8e3b99..c88d49f 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
     <string name="back_button_text" msgid="1469718707134137085">"返回"</string>
     <string name="handle_text" msgid="1766582106752184456">"处理"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"分屏"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"更多"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"悬浮"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 8e5fd7f..8bf304e 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
     <string name="back_button_text" msgid="1469718707134137085">"返去"</string>
     <string name="handle_text" msgid="1766582106752184456">"控點"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"分割螢幕"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"更多"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 17557f9..17ea42d3 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
     <string name="back_button_text" msgid="1469718707134137085">"返回"</string>
     <string name="handle_text" msgid="1766582106752184456">"控點"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"分割畫面"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"更多"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 01af7b8..414706f 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -86,14 +86,9 @@
     <string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
     <string name="back_button_text" msgid="1469718707134137085">"Emuva"</string>
     <string name="handle_text" msgid="1766582106752184456">"Isibambo"</string>
-    <!-- no translation found for fullscreen_text (1162316685217676079) -->
-    <skip />
-    <!-- no translation found for desktop_text (1077633567027630454) -->
-    <skip />
-    <!-- no translation found for split_screen_text (1396336058129570886) -->
-    <skip />
-    <!-- no translation found for more_button_text (3655388105592893530) -->
-    <skip />
-    <!-- no translation found for float_button_text (9221657008391364581) -->
-    <skip />
+    <string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string>
+    <string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string>
+    <string name="split_screen_text" msgid="1396336058129570886">"Hlukanisa isikrini"</string>
+    <string name="more_button_text" msgid="3655388105592893530">"Okwengeziwe"</string>
+    <string name="float_button_text" msgid="9221657008391364581">"Iflowuthi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index df5f921..c6197c8 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -111,4 +111,8 @@
 
     <!-- Whether to dim a split-screen task when the other is the IME target -->
     <bool name="config_dimNonImeAttachedSide">true</bool>
+
+    <!-- Components support to launch multiple instances into split-screen -->
+    <string-array name="config_componentsSupportMultiInstancesSplit">
+    </string-array>
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 4367936..e58e785 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,14 +16,12 @@
 
 package com.android.wm.shell;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
 import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
 
@@ -48,7 +46,6 @@
 import android.window.StartingWindowRemovalInfo;
 import android.window.TaskAppearedInfo;
 import android.window.TaskOrganizer;
-import android.window.WindowContainerTransaction;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
@@ -567,6 +564,22 @@
         }
     }
 
+    /**
+     * Return list of {@link RunningTaskInfo}s for the given display.
+     *
+     * @return filtered list of tasks or empty list
+     */
+    public ArrayList<RunningTaskInfo> getRunningTasks(int displayId) {
+        ArrayList<RunningTaskInfo> result = new ArrayList<>();
+        for (int i = 0; i < mTasks.size(); i++) {
+            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
+            if (taskInfo.displayId == displayId) {
+                result.add(taskInfo);
+            }
+        }
+        return result;
+    }
+
     /** Gets running task by taskId. Returns {@code null} if no such task observed. */
     @Nullable
     public RunningTaskInfo getRunningTaskInfo(int taskId) {
@@ -693,57 +706,6 @@
         taskListener.reparentChildSurfaceToTask(taskId, sc, t);
     }
 
-    /**
-     * Create a {@link WindowContainerTransaction} to clear task bounds.
-     *
-     * Only affects tasks that have {@link RunningTaskInfo#getActivityType()} set to
-     * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
-     *
-     * @param displayId display id for tasks that will have bounds cleared
-     * @return {@link WindowContainerTransaction} with pending operations to clear bounds
-     */
-    public WindowContainerTransaction prepareClearBoundsForStandardTasks(int displayId) {
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks: displayId=%d", displayId);
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        for (int i = 0; i < mTasks.size(); i++) {
-            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
-            if ((taskInfo.displayId == displayId) && (taskInfo.getActivityType()
-                    == WindowConfiguration.ACTIVITY_TYPE_STANDARD)) {
-                ProtoLog.d(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
-                        taskInfo.token, taskInfo);
-                wct.setBounds(taskInfo.token, null);
-            }
-        }
-        return wct;
-    }
-
-    /**
-     * Create a {@link WindowContainerTransaction} to clear task level freeform setting.
-     *
-     * Only affects tasks that have {@link RunningTaskInfo#getActivityType()} set to
-     * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
-     *
-     * @param displayId display id for tasks that will have windowing mode reset to {@link
-     *                  WindowConfiguration#WINDOWING_MODE_UNDEFINED}
-     * @return {@link WindowContainerTransaction} with pending operations to clear windowing mode
-     */
-    public WindowContainerTransaction prepareClearFreeformForStandardTasks(int displayId) {
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks: displayId=%d", displayId);
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        for (int i = 0; i < mTasks.size(); i++) {
-            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
-            if (taskInfo.displayId == displayId
-                    && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
-                    && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
-                ProtoLog.d(WM_SHELL_DESKTOP_MODE,
-                        "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
-                        taskInfo);
-                wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
-            }
-        }
-        return wct;
-    }
-
     private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
             int event) {
         ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;
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 5b7ed27..6e116b9 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
@@ -163,7 +163,8 @@
 
     /** Showing resizing hint. */
     public void onResizing(ActivityManager.RunningTaskInfo resizingTask, Rect newBounds,
-            Rect sideBounds, SurfaceControl.Transaction t, int offsetX, int offsetY) {
+            Rect sideBounds, SurfaceControl.Transaction t, int offsetX, int offsetY,
+            boolean immediately) {
         if (mResizingIconView == null) {
             return;
         }
@@ -178,8 +179,8 @@
 
         final boolean show =
                 newBounds.width() > mBounds.width() || newBounds.height() > mBounds.height();
-        final boolean animate = show != mShown;
-        if (animate && mFadeAnimator != null && mFadeAnimator.isRunning()) {
+        final boolean update = show != mShown;
+        if (update && mFadeAnimator != null && mFadeAnimator.isRunning()) {
             // If we need to animate and animator still running, cancel it before we ensure both
             // background and icon surfaces are non null for next animation.
             mFadeAnimator.cancel();
@@ -192,7 +193,7 @@
                     .setLayer(mBackgroundLeash, Integer.MAX_VALUE - 1);
         }
 
-        if (mGapBackgroundLeash == null) {
+        if (mGapBackgroundLeash == null && !immediately) {
             final boolean isLandscape = newBounds.height() == sideBounds.height();
             final int left = isLandscape ? mBounds.width() : 0;
             final int top = isLandscape ? 0 : mBounds.height();
@@ -221,8 +222,13 @@
                 newBounds.width() / 2 - mIconSize / 2,
                 newBounds.height() / 2 - mIconSize / 2);
 
-        if (animate) {
-            startFadeAnimation(show, null /* finishedConsumer */);
+        if (update) {
+            if (immediately) {
+                t.setVisibility(mBackgroundLeash, show);
+                t.setVisibility(mIconLeash, show);
+            } else {
+                startFadeAnimation(show, null /* finishedConsumer */);
+            }
             mShown = show;
         }
     }
@@ -319,10 +325,12 @@
             @Override
             public void onAnimationStart(@NonNull Animator animation) {
                 if (show) {
-                    animT.show(mBackgroundLeash).show(mIconLeash).show(mGapBackgroundLeash).apply();
-                } else {
-                    animT.hide(mGapBackgroundLeash).apply();
+                    animT.show(mBackgroundLeash).show(mIconLeash);
                 }
+                if (mGapBackgroundLeash != null) {
+                    animT.setVisibility(mGapBackgroundLeash, show);
+                }
+                animT.apply();
             }
 
             @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 839edc8..ec9e6f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -83,8 +83,8 @@
 
     private static final int FLING_RESIZE_DURATION = 250;
     private static final int FLING_SWITCH_DURATION = 350;
-    private static final int FLING_ENTER_DURATION = 350;
-    private static final int FLING_EXIT_DURATION = 350;
+    private static final int FLING_ENTER_DURATION = 450;
+    private static final int FLING_EXIT_DURATION = 450;
 
     private int mDividerWindowWidth;
     private int mDividerInsets;
@@ -601,7 +601,7 @@
         animator.start();
     }
 
-    /** Swich both surface position with animation. */
+    /** Switch both surface position with animation. */
     public void splitSwitching(SurfaceControl.Transaction t, SurfaceControl leash1,
             SurfaceControl leash2, Consumer<Rect> finishCallback) {
         final boolean isLandscape = isLandscape();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 34ff6d8..abc4024 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -16,8 +16,11 @@
 
 package com.android.wm.shell.desktopmode;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -151,21 +154,18 @@
 
         int displayId = mContext.getDisplayId();
 
+        ArrayList<RunningTaskInfo> runningTasks = mShellTaskOrganizer.getRunningTasks(displayId);
+
         WindowContainerTransaction wct = new WindowContainerTransaction();
-        // Reset freeform windowing mode that is set per task level (tasks should inherit
-        // container value)
-        wct.merge(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(displayId),
-                true /* transfer */);
-        int targetWindowingMode;
+        // Reset freeform windowing mode that is set per task level so tasks inherit it
+        clearFreeformForStandardTasks(runningTasks, wct);
         if (active) {
-            targetWindowingMode = WINDOWING_MODE_FREEFORM;
+            moveHomeBehindVisibleTasks(runningTasks, wct);
+            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FREEFORM, wct);
         } else {
-            targetWindowingMode = WINDOWING_MODE_FULLSCREEN;
-            // Clear any resized bounds
-            wct.merge(mShellTaskOrganizer.prepareClearBoundsForStandardTasks(displayId),
-                    true /* transfer */);
+            clearBoundsForStandardTasks(runningTasks, wct);
+            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FULLSCREEN, wct);
         }
-        prepareWindowingModeChange(wct, displayId, targetWindowingMode);
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             mTransitions.startTransition(TRANSIT_CHANGE, wct, null);
         } else {
@@ -173,17 +173,69 @@
         }
     }
 
-    private void prepareWindowingModeChange(WindowContainerTransaction wct,
-            int displayId, @WindowConfiguration.WindowingMode int windowingMode) {
-        DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer
-                .getDisplayAreaInfo(displayId);
+    private WindowContainerTransaction clearBoundsForStandardTasks(
+            ArrayList<RunningTaskInfo> runningTasks, WindowContainerTransaction wct) {
+        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks");
+        for (RunningTaskInfo taskInfo : runningTasks) {
+            if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
+                ProtoLog.v(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
+                        taskInfo.token, taskInfo);
+                wct.setBounds(taskInfo.token, null);
+            }
+        }
+        return wct;
+    }
+
+    private void clearFreeformForStandardTasks(ArrayList<RunningTaskInfo> runningTasks,
+            WindowContainerTransaction wct) {
+        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks");
+        for (RunningTaskInfo taskInfo : runningTasks) {
+            if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
+                    && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
+                ProtoLog.v(WM_SHELL_DESKTOP_MODE,
+                        "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
+                        taskInfo);
+                wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
+            }
+        }
+    }
+
+    private void moveHomeBehindVisibleTasks(ArrayList<RunningTaskInfo> runningTasks,
+            WindowContainerTransaction wct) {
+        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks");
+        RunningTaskInfo homeTask = null;
+        ArrayList<RunningTaskInfo> visibleTasks = new ArrayList<>();
+        for (RunningTaskInfo taskInfo : runningTasks) {
+            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
+                homeTask = taskInfo;
+            } else if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
+                    && taskInfo.isVisible()) {
+                visibleTasks.add(taskInfo);
+            }
+        }
+        if (homeTask == null) {
+            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: home task not found");
+        } else {
+            ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: visible tasks %d",
+                    visibleTasks.size());
+            wct.reorder(homeTask.getToken(), true /* onTop */);
+            for (RunningTaskInfo task : visibleTasks) {
+                wct.reorder(task.getToken(), true /* onTop */);
+            }
+        }
+    }
+
+    private void setDisplayAreaWindowingMode(int displayId,
+            @WindowConfiguration.WindowingMode int windowingMode, WindowContainerTransaction wct) {
+        DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(
+                displayId);
         if (displayAreaInfo == null) {
             ProtoLog.e(WM_SHELL_DESKTOP_MODE,
                     "unable to update windowing mode for display %d display not found", displayId);
             return;
         }
 
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE,
+        ProtoLog.v(WM_SHELL_DESKTOP_MODE,
                 "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId,
                 displayAreaInfo.configuration.windowConfiguration.getWindowingMode(),
                 windowingMode);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
index eb08d0e..56aa742 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -86,8 +86,8 @@
     /**
      * Starts a pair of intent and task in one transition.
      */
-    oneway void startIntentAndTask(in PendingIntent pendingIntent, in Intent fillInIntent,
-            in Bundle options1, int taskId, in Bundle options2, int sidePosition, float splitRatio,
+    oneway void startIntentAndTask(in PendingIntent pendingIntent, in Bundle options1, int taskId,
+            in Bundle options2, int sidePosition, float splitRatio,
             in RemoteTransition remoteTransition, in InstanceId instanceId) = 16;
 
     /**
@@ -95,7 +95,7 @@
      */
     oneway void startShortcutAndTask(in ShortcutInfo shortcutInfo, in Bundle options1, int taskId,
             in Bundle options2, int splitPosition, float splitRatio,
-             in RemoteTransition remoteTransition, in InstanceId instanceId) = 17;
+            in RemoteTransition remoteTransition, in InstanceId instanceId) = 17;
 
     /**
      * Version of startTasks using legacy transition system.
@@ -108,9 +108,8 @@
      * Starts a pair of intent and task using legacy transition system.
      */
     oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent,
-            in Intent fillInIntent, in Bundle options1, int taskId, in Bundle options2,
-            int splitPosition, float splitRatio, in RemoteAnimationAdapter adapter,
-            in InstanceId instanceId) = 12;
+            in Bundle options1, int taskId, in Bundle options2, int splitPosition, float splitRatio,
+            in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 12;
 
     /**
      * Starts a pair of shortcut and task using legacy transition system.
@@ -120,6 +119,21 @@
             in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 15;
 
     /**
+     * Start a pair of intents using legacy transition system.
+     */
+    oneway void startIntentsWithLegacyTransition(in PendingIntent pendingIntent1,
+            in Bundle options1, in PendingIntent pendingIntent2, in Bundle options2,
+            int splitPosition, float splitRatio, in RemoteAnimationAdapter adapter,
+            in InstanceId instanceId) = 18;
+
+    /**
+     * Start a pair of intents in one transition.
+     */
+    oneway void startIntents(in PendingIntent pendingIntent1, in Bundle options1,
+            in PendingIntent pendingIntent2, in Bundle options2, int splitPosition,
+            float splitRatio, in RemoteTransition remoteTransition, in InstanceId instanceId) = 19;
+
+    /**
      * Blocking call that notifies and gets additional split-screen targets when entering
      * recents (for example: the dividerBar).
      * @param appTargets apps that will be re-parented to display area
@@ -133,4 +147,4 @@
      */
     RemoteAnimationTarget[] onStartingSplitLegacy(in RemoteAnimationTarget[] appTargets) = 14;
 }
-// Last id = 17
+// Last id = 19
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index c6a2b83..1774dd5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -32,6 +33,8 @@
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
 import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
@@ -60,13 +63,12 @@
 
 import androidx.annotation.BinderThread;
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.R;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
@@ -166,8 +168,11 @@
     private final IconProvider mIconProvider;
     private final Optional<RecentTasksController> mRecentTasksOptional;
     private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler;
+    private final String[] mMultiInstancesComponents;
 
-    private StageCoordinator mStageCoordinator;
+    @VisibleForTesting
+    StageCoordinator mStageCoordinator;
+
     // Only used for the legacy recents animation from splitscreen to allow the tasks to be animated
     // outside the bounds of the roots by being reparented into a higher level fullscreen container
     private SurfaceControl mGoingToRecentsTasksLayer;
@@ -210,6 +215,51 @@
         if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
             shellInit.addInitCallback(this::onInit, this);
         }
+
+        // TODO(255224696): Remove the config once having a way for client apps to opt-in
+        //                  multi-instances split.
+        mMultiInstancesComponents = mContext.getResources()
+                .getStringArray(R.array.config_componentsSupportMultiInstancesSplit);
+    }
+
+    @VisibleForTesting
+    SplitScreenController(Context context,
+            ShellInit shellInit,
+            ShellCommandHandler shellCommandHandler,
+            ShellController shellController,
+            ShellTaskOrganizer shellTaskOrganizer,
+            SyncTransactionQueue syncQueue,
+            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
+            DisplayController displayController,
+            DisplayImeController displayImeController,
+            DisplayInsetsController displayInsetsController,
+            DragAndDropController dragAndDropController,
+            Transitions transitions,
+            TransactionPool transactionPool,
+            IconProvider iconProvider,
+            RecentTasksController recentTasks,
+            ShellExecutor mainExecutor,
+            StageCoordinator stageCoordinator) {
+        mShellCommandHandler = shellCommandHandler;
+        mShellController = shellController;
+        mTaskOrganizer = shellTaskOrganizer;
+        mSyncQueue = syncQueue;
+        mContext = context;
+        mRootTDAOrganizer = rootTDAOrganizer;
+        mMainExecutor = mainExecutor;
+        mDisplayController = displayController;
+        mDisplayImeController = displayImeController;
+        mDisplayInsetsController = displayInsetsController;
+        mDragAndDropController = dragAndDropController;
+        mTransitions = transitions;
+        mTransactionPool = transactionPool;
+        mIconProvider = iconProvider;
+        mRecentTasksOptional = Optional.of(recentTasks);
+        mStageCoordinator = stageCoordinator;
+        mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
+        shellInit.addInitCallback(this::onInit, this);
+        mMultiInstancesComponents = mContext.getResources()
+                .getStringArray(R.array.config_componentsSupportMultiInstancesSplit);
     }
 
     public SplitScreen asSplitScreen() {
@@ -471,72 +521,140 @@
         startIntent(intent, fillInIntent, position, options);
     }
 
+    private void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent,
+            @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
+            @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
+            InstanceId instanceId) {
+        Intent fillInIntent = null;
+        if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)
+                && supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+            fillInIntent = new Intent();
+            fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+        mStageCoordinator.startIntentAndTaskWithLegacyTransition(pendingIntent, fillInIntent,
+                options1, taskId, options2, splitPosition, splitRatio, adapter, instanceId);
+    }
+
+    private void startIntentAndTask(PendingIntent pendingIntent, @Nullable Bundle options1,
+            int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
+            float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
+        Intent fillInIntent = null;
+        if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)
+                && supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+            fillInIntent = new Intent();
+            fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+        mStageCoordinator.startIntentAndTask(pendingIntent, fillInIntent, options1, taskId,
+                options2, splitPosition, splitRatio, remoteTransition, instanceId);
+    }
+
+    private void startIntentsWithLegacyTransition(PendingIntent pendingIntent1,
+            @Nullable Bundle options1, PendingIntent pendingIntent2,
+            @Nullable Bundle options2, @SplitPosition int splitPosition,
+            float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+        Intent fillInIntent1 = null;
+        Intent fillInIntent2 = null;
+        if (launchSameComponentAdjacently(pendingIntent1, pendingIntent2)
+                && supportMultiInstancesSplit(pendingIntent1.getIntent().getComponent())) {
+            fillInIntent1 = new Intent();
+            fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+            fillInIntent2 = new Intent();
+            fillInIntent2.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+        mStageCoordinator.startIntentsWithLegacyTransition(pendingIntent1, fillInIntent1, options1,
+                pendingIntent2, fillInIntent2, options2, splitPosition, splitRatio, adapter,
+                instanceId);
+    }
+
     @Override
     public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent,
             @SplitPosition int position, @Nullable Bundle options) {
-        if (fillInIntent == null) {
-            fillInIntent = new Intent();
-        }
-        // Flag this as a no-user-action launch to prevent sending user leaving event to the
-        // current top activity since it's going to be put into another side of the split. This
-        // prevents the current top activity from going into pip mode due to user leaving event.
+        // Flag this as a no-user-action launch to prevent sending user leaving event to the current
+        // top activity since it's going to be put into another side of the split. This prevents the
+        // current top activity from going into pip mode due to user leaving event.
+        if (fillInIntent == null) fillInIntent = new Intent();
         fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
 
-        // Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the
-        // split and there is no reusable background task.
-        if (shouldAddMultipleTaskFlag(intent.getIntent(), position)) {
-            final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional.isPresent()
-                    ? mRecentTasksOptional.get().findTaskInBackground(
-                            intent.getIntent().getComponent())
-                    : null;
-            if (taskInfo != null) {
-                startTask(taskInfo.taskId, position, options);
+        if (launchSameComponentAdjacently(intent, position, INVALID_TASK_ID)) {
+            final ComponentName launching = intent.getIntent().getComponent();
+            if (supportMultiInstancesSplit(launching)) {
+                // To prevent accumulating large number of instances in the background, reuse task
+                // in the background with priority.
+                final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional
+                        .map(recentTasks -> recentTasks.findTaskInBackground(launching))
+                        .orElse(null);
+                if (taskInfo != null) {
+                    startTask(taskInfo.taskId, position, options);
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+                            "Start task in background");
+                    return;
+                }
+
+                // Flag with MULTIPLE_TASK if this is launching the same activity into both sides of
+                // the split and there is no reusable background task.
+                fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
+            } else if (isSplitScreenVisible()) {
+                mStageCoordinator.switchSplitPosition("startIntent");
                 return;
             }
-            fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
         }
 
-        if (!ENABLE_SHELL_TRANSITIONS) {
-            mStageCoordinator.startIntentLegacy(intent, fillInIntent, position, options);
-            return;
-        }
         mStageCoordinator.startIntent(intent, fillInIntent, position, options);
     }
 
     /** Returns {@code true} if it's launching the same component on both sides of the split. */
-    @VisibleForTesting
-    boolean shouldAddMultipleTaskFlag(@Nullable Intent startIntent, @SplitPosition int position) {
-        if (startIntent == null) {
-            return false;
-        }
+    private boolean launchSameComponentAdjacently(@Nullable PendingIntent pendingIntent,
+            @SplitPosition int position, int taskId) {
+        if (pendingIntent == null || pendingIntent.getIntent() == null) return false;
 
-        final ComponentName launchingActivity = startIntent.getComponent();
-        if (launchingActivity == null) {
-            return false;
-        }
+        final ComponentName launchingActivity = pendingIntent.getIntent().getComponent();
+        if (launchingActivity == null) return false;
 
-        if (isSplitScreenVisible()) {
-            // To prevent users from constantly dropping the same app to the same side resulting in
-            // a large number of instances in the background.
-            final ActivityManager.RunningTaskInfo targetTaskInfo = getTaskInfo(position);
-            final ComponentName targetActivity = targetTaskInfo != null
-                    ? targetTaskInfo.baseIntent.getComponent() : null;
-            if (Objects.equals(launchingActivity, targetActivity)) {
-                return false;
+        if (taskId != INVALID_TASK_ID) {
+            final ActivityManager.RunningTaskInfo taskInfo =
+                    mTaskOrganizer.getRunningTaskInfo(taskId);
+            if (taskInfo != null) {
+                return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity);
             }
-
-            // Allow users to start a new instance the same to adjacent side.
-            final ActivityManager.RunningTaskInfo pairedTaskInfo =
-                    getTaskInfo(SplitLayout.reversePosition(position));
-            final ComponentName pairedActivity = pairedTaskInfo != null
-                    ? pairedTaskInfo.baseIntent.getComponent() : null;
-            return Objects.equals(launchingActivity, pairedActivity);
+            return false;
         }
 
-        final ActivityManager.RunningTaskInfo taskInfo = getFocusingTaskInfo();
-        if (taskInfo != null && isValidToEnterSplitScreen(taskInfo)) {
-            return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity);
+        if (!isSplitScreenVisible()) {
+            // Split screen is not yet activated, check if the current top running task is valid to
+            // split together.
+            final ActivityManager.RunningTaskInfo taskInfo = getFocusingTaskInfo();
+            if (taskInfo != null && isValidToEnterSplitScreen(taskInfo)) {
+                return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity);
+            }
+            return false;
+        }
+
+        // Compare to the adjacent side of the split to determine if this is launching the same
+        // component adjacently.
+        final ActivityManager.RunningTaskInfo pairedTaskInfo =
+                getTaskInfo(SplitLayout.reversePosition(position));
+        final ComponentName pairedActivity = pairedTaskInfo != null
+                ? pairedTaskInfo.baseIntent.getComponent() : null;
+        return Objects.equals(launchingActivity, pairedActivity);
+    }
+
+    private boolean launchSameComponentAdjacently(PendingIntent pendingIntent1,
+            PendingIntent pendingIntent2) {
+        return Objects.equals(pendingIntent1.getIntent().getComponent(),
+                pendingIntent2.getIntent().getComponent());
+    }
+
+    @VisibleForTesting
+    /** Returns {@code true} if the component supports multi-instances split. */
+    boolean supportMultiInstancesSplit(@Nullable ComponentName launching) {
+        if (launching == null) return false;
+
+        final String componentName = launching.flattenToString();
+        for (int i = 0; i < mMultiInstancesComponents.length; i++) {
+            if (mMultiInstancesComponents[i].equals(componentName)) {
+                return true;
+            }
         }
 
         return false;
@@ -839,14 +957,13 @@
 
         @Override
         public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent,
-                Intent fillInIntent, Bundle options1, int taskId, Bundle options2,
-                int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
-                InstanceId instanceId) {
+                Bundle options1, int taskId, Bundle options2, int splitPosition, float splitRatio,
+                RemoteAnimationAdapter adapter, InstanceId instanceId) {
             executeRemoteCallWithTaskPermission(mController,
                     "startIntentAndTaskWithLegacyTransition", (controller) ->
-                            controller.mStageCoordinator.startIntentAndTaskWithLegacyTransition(
-                                    pendingIntent, fillInIntent, options1, taskId, options2,
-                                    splitPosition, splitRatio, adapter, instanceId));
+                            controller.startIntentAndTaskWithLegacyTransition(pendingIntent,
+                                    options1, taskId, options2, splitPosition, splitRatio, adapter,
+                                    instanceId));
         }
 
         @Override
@@ -872,14 +989,13 @@
         }
 
         @Override
-        public void startIntentAndTask(PendingIntent pendingIntent, Intent fillInIntent,
-                @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
-                @SplitPosition int splitPosition, float splitRatio,
-                @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
+        public void startIntentAndTask(PendingIntent pendingIntent, @Nullable Bundle options1,
+                int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
+                float splitRatio, @Nullable RemoteTransition remoteTransition,
+                InstanceId instanceId) {
             executeRemoteCallWithTaskPermission(mController, "startIntentAndTask",
-                    (controller) -> controller.mStageCoordinator.startIntentAndTask(pendingIntent,
-                            fillInIntent, options1, taskId, options2, splitPosition, splitRatio,
-                            remoteTransition, instanceId));
+                    (controller) -> controller.startIntentAndTask(pendingIntent, options1, taskId,
+                            options2, splitPosition, splitRatio, remoteTransition, instanceId));
         }
 
         @Override
@@ -894,6 +1010,27 @@
         }
 
         @Override
+        public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1,
+                @Nullable Bundle options1, PendingIntent pendingIntent2, @Nullable Bundle options2,
+                @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
+                InstanceId instanceId) {
+            executeRemoteCallWithTaskPermission(mController, "startIntentsWithLegacyTransition",
+                    (controller) ->
+                        controller.startIntentsWithLegacyTransition(
+                                pendingIntent1, options1, pendingIntent2, options2, splitPosition,
+                                splitRatio, adapter, instanceId)
+                    );
+        }
+
+        @Override
+        public void startIntents(PendingIntent pendingIntent1, @Nullable Bundle options1,
+                PendingIntent pendingIntent2, @Nullable Bundle options2,
+                @SplitPosition int splitPosition, float splitRatio,
+                @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
+            // TODO(b/259368992): To be implemented.
+        }
+
+        @Override
         public void startShortcut(String packageName, String shortcutId, int position,
                 @Nullable Bundle options, UserHandle user, InstanceId instanceId) {
             executeRemoteCallWithTaskPermission(mController, "startShortcut",
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 e888c6f..acb71a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -24,7 +24,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -170,6 +169,7 @@
     private ValueAnimator mDividerFadeInAnimator;
     private boolean mDividerVisible;
     private boolean mKeyguardShowing;
+    private boolean mShowDecorImmediately;
     private final SyncTransactionQueue mSyncQueue;
     private final ShellTaskOrganizer mTaskOrganizer;
     private final Context mContext;
@@ -428,6 +428,11 @@
     /** Launches an activity into split. */
     void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
             @Nullable Bundle options) {
+        if (!ENABLE_SHELL_TRANSITIONS) {
+            startIntentLegacy(intent, fillInIntent, position, options);
+            return;
+        }
+
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         final WindowContainerTransaction evictWct = new WindowContainerTransaction();
         prepareEvictChildTasks(position, evictWct);
@@ -441,13 +446,7 @@
         prepareEnterSplitScreen(wct, null /* taskInfo */, position);
 
         mSplitTransitions.startEnterTransition(transitType, wct, null, this,
-                aborted -> {
-                    // Switch the split position if launching as MULTIPLE_TASK failed.
-                    if (aborted && (fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
-                        setSideStagePositionAnimated(
-                                SplitLayout.reversePosition(mSideStagePosition));
-                    }
-                } /* consumedCallback */,
+                null /* consumedCallback */,
                 (finishWct, finishT) -> {
                     if (!evictWct.isEmpty()) {
                         finishWct.merge(evictWct, true);
@@ -457,7 +456,7 @@
 
     /** Launches an activity into split by legacy transition. */
     void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
-            @SplitPosition int position, @androidx.annotation.Nullable Bundle options) {
+            @SplitPosition int position, @Nullable Bundle options) {
         final WindowContainerTransaction evictWct = new WindowContainerTransaction();
         prepareEvictChildTasks(position, evictWct);
 
@@ -473,12 +472,6 @@
                                 exitSplitScreen(mMainStage.getChildCount() == 0
                                         ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
                         mSplitUnsupportedToast.show();
-                    } else {
-                        // Switch the split position if launching as MULTIPLE_TASK failed.
-                        if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
-                            setSideStagePosition(SplitLayout.reversePosition(
-                                    getSideStagePosition()), null);
-                        }
                     }
 
                     // Do nothing when the animation was cancelled.
@@ -596,8 +589,7 @@
     /** Starts a pair of tasks using legacy transition. */
     void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
             int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
-            float splitRatio, RemoteAnimationAdapter adapter,
-            InstanceId instanceId) {
+            float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (options1 == null) options1 = new Bundle();
         addActivityOptions(options1, mSideStage);
@@ -607,7 +599,20 @@
                 instanceId);
     }
 
-    /** Starts a pair of intent and task using legacy transition. */
+    /** Starts a pair of intents using legacy transition. */
+    void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, Intent fillInIntent1,
+            @Nullable Bundle options1, PendingIntent pendingIntent2, Intent fillInIntent2,
+            @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
+            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (options1 == null) options1 = new Bundle();
+        addActivityOptions(options1, mSideStage);
+        wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
+
+        startWithLegacyTransition(wct, pendingIntent2, fillInIntent2, options2, splitPosition,
+                splitRatio, adapter, instanceId);
+    }
+
     void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent,
             @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
             @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
@@ -635,12 +640,29 @@
                 instanceId);
     }
 
+    private void startWithLegacyTransition(WindowContainerTransaction wct,
+            @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
+            @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
+            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+        startWithLegacyTransition(wct, INVALID_TASK_ID, mainPendingIntent, mainFillInIntent,
+                mainOptions, sidePosition, splitRatio, adapter, instanceId);
+    }
+
+    private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
+            @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
+            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+        startWithLegacyTransition(wct, mainTaskId, null /* mainPendingIntent */,
+                null /* mainFillInIntent */, mainOptions, sidePosition, splitRatio, adapter,
+                instanceId);
+    }
+
     /**
      * @param wct        transaction to start the first task
      * @param instanceId if {@code null}, will not log. Otherwise it will be used in
      *                   {@link SplitscreenEventLogger#logEnter(float, int, int, int, int, boolean)}
      */
     private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
+            @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
             @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
             RemoteAnimationAdapter adapter, InstanceId instanceId) {
         // Init divider first to make divider leash for remote animation target.
@@ -709,7 +731,11 @@
         if (mainOptions == null) mainOptions = new Bundle();
         addActivityOptions(mainOptions, mMainStage);
         updateWindowBounds(mSplitLayout, wct);
-        wct.startTask(mainTaskId, mainOptions);
+        if (mainTaskId == INVALID_TASK_ID) {
+            wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, mainOptions);
+        } else {
+            wct.startTask(mainTaskId, mainOptions);
+        }
         wct.reorder(mRootTaskInfo.token, true);
         wct.setForceTranslucent(mRootTaskInfo.token, false);
 
@@ -771,9 +797,8 @@
         mSideStage.evictInvisibleChildren(wct);
     }
 
-    Bundle resolveStartStage(@StageType int stage,
-            @SplitPosition int position, @androidx.annotation.Nullable Bundle options,
-            @androidx.annotation.Nullable WindowContainerTransaction wct) {
+    Bundle resolveStartStage(@StageType int stage, @SplitPosition int position,
+            @Nullable Bundle options, @Nullable WindowContainerTransaction wct) {
         switch (stage) {
             case STAGE_TYPE_UNDEFINED: {
                 if (position != SPLIT_POSITION_UNDEFINED) {
@@ -844,9 +869,8 @@
                 : mMainStage.getTopVisibleChildTaskId();
     }
 
-    void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) {
-        if (mSideStagePosition == sideStagePosition) return;
-        SurfaceControl.Transaction t = mTransactionPool.acquire();
+    void switchSplitPosition(String reason) {
+        final SurfaceControl.Transaction t = mTransactionPool.acquire();
         mTempRect1.setEmpty();
         final StageTaskListener topLeftStage =
                 mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
@@ -886,6 +910,11 @@
                         va.start();
                     });
                 });
+
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Switch split position: %s", reason);
+        mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+                getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+                mSplitLayout.isLandscape());
     }
 
     void setSideStagePosition(@SplitPosition int sideStagePosition,
@@ -1561,6 +1590,7 @@
                 if (mLogger.isEnterRequestedByDrag()) {
                     updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
                 } else {
+                    mShowDecorImmediately = true;
                     mSplitLayout.flingDividerToCenter();
                 }
             });
@@ -1617,10 +1647,7 @@
 
     @Override
     public void onDoubleTappedDivider() {
-        setSideStagePositionAnimated(SplitLayout.reversePosition(mSideStagePosition));
-        mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
-                getSideStagePosition(), mSideStage.getTopChildTaskUid(),
-                mSplitLayout.isLandscape());
+        switchSplitPosition("double tap");
     }
 
     @Override
@@ -1639,14 +1666,16 @@
         updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
         getMainStageBounds(mTempRect1);
         getSideStageBounds(mTempRect2);
-        mMainStage.onResizing(mTempRect1, mTempRect2, t, offsetX, offsetY);
-        mSideStage.onResizing(mTempRect2, mTempRect1, t, offsetX, offsetY);
+        mMainStage.onResizing(mTempRect1, mTempRect2, t, offsetX, offsetY, mShowDecorImmediately);
+        mSideStage.onResizing(mTempRect2, mTempRect1, t, offsetX, offsetY, mShowDecorImmediately);
         t.apply();
         mTransactionPool.release(t);
     }
 
     @Override
     public void onLayoutSizeChanged(SplitLayout layout) {
+        // Reset this flag every time onLayoutSizeChanged.
+        mShowDecorImmediately = false;
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         updateWindowBounds(layout, wct);
         sendOnBoundsChanged();
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 acad5d9..bcf900b 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
@@ -289,10 +289,10 @@
     }
 
     void onResizing(Rect newBounds, Rect sideBounds, SurfaceControl.Transaction t, int offsetX,
-            int offsetY) {
+            int offsetY, boolean immediately) {
         if (mSplitDecorManager != null && mRootTaskInfo != null) {
             mSplitDecorManager.onResizing(mRootTaskInfo, newBounds, sideBounds, t, offsetX,
-                    offsetY);
+                    offsetY, immediately);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index ca15f00..ebe5c5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -124,7 +124,8 @@
         TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration,
                 mDragStartListener);
         CaptionTouchEventListener touchEventListener =
-                new CaptionTouchEventListener(taskInfo, taskPositioner);
+                new CaptionTouchEventListener(taskInfo, taskPositioner,
+                        windowDecoration.getDragDetector());
         windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
         windowDecoration.setDragResizeCallback(taskPositioner);
         setupWindowDecorationForTransition(taskInfo, startT, finishT);
@@ -173,16 +174,18 @@
         private final int mTaskId;
         private final WindowContainerToken mTaskToken;
         private final DragResizeCallback mDragResizeCallback;
+        private final DragDetector mDragDetector;
 
         private int mDragPointerId = -1;
-        private boolean mDragActive = false;
 
         private CaptionTouchEventListener(
                 RunningTaskInfo taskInfo,
-                DragResizeCallback dragResizeCallback) {
+                DragResizeCallback dragResizeCallback,
+                DragDetector dragDetector) {
             mTaskId = taskInfo.taskId;
             mTaskToken = taskInfo.token;
             mDragResizeCallback = dragResizeCallback;
+            mDragDetector = dragDetector;
         }
 
         @Override
@@ -231,19 +234,21 @@
 
         @Override
         public boolean onTouch(View v, MotionEvent e) {
+            boolean isDrag = false;
             int id = v.getId();
             if (id != R.id.caption_handle && id != R.id.caption) {
                 return false;
             }
-            if (id == R.id.caption_handle || mDragActive) {
+            if (id == R.id.caption_handle) {
+                isDrag = mDragDetector.detectDragEvent(e);
                 handleEventForMove(e);
             }
             if (e.getAction() != MotionEvent.ACTION_DOWN) {
-                return false;
+                return isDrag;
             }
             RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
             if (taskInfo.isFocused) {
-                return false;
+                return isDrag;
             }
             WindowContainerTransaction wct = new WindowContainerTransaction();
             wct.reorder(mTaskToken, true /* onTop */);
@@ -251,6 +256,10 @@
             return true;
         }
 
+        /**
+         * @param e {@link MotionEvent} to process
+         * @return {@code true} if a drag is happening; or {@code false} if it is not
+         */
         private void handleEventForMove(MotionEvent e) {
             RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
             int windowingMode =  mDesktopModeController
@@ -259,12 +268,12 @@
                 return;
             }
             switch (e.getActionMasked()) {
-                case MotionEvent.ACTION_DOWN:
-                    mDragActive = true;
-                    mDragPointerId  = e.getPointerId(0);
+                case MotionEvent.ACTION_DOWN: {
+                    mDragPointerId = e.getPointerId(0);
                     mDragResizeCallback.onDragResizeStart(
                             0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
                     break;
+                }
                 case MotionEvent.ACTION_MOVE: {
                     int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragResizeCallback.onDragResizeMove(
@@ -273,7 +282,6 @@
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
-                    mDragActive = false;
                     int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
                             .stableInsets().top;
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 03cad04..affde30 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
@@ -62,6 +62,8 @@
 
     private boolean mDesktopActive;
 
+    private DragDetector mDragDetector;
+
     private AdditionalWindow mHandleMenu;
 
     CaptionWindowDecoration(
@@ -79,6 +81,7 @@
         mChoreographer = choreographer;
         mSyncQueue = syncQueue;
         mDesktopActive = DesktopModeStatus.isActive(mContext);
+        mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
     }
 
     void setCaptionListeners(
@@ -92,6 +95,10 @@
         mDragResizeCallback = dragResizeCallback;
     }
 
+    DragDetector getDragDetector() {
+        return mDragDetector;
+    }
+
     @Override
     void relayout(ActivityManager.RunningTaskInfo taskInfo) {
         final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
@@ -182,6 +189,8 @@
         }
 
         int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop();
+        mDragDetector.setTouchSlop(touchSlop);
+
         int resize_handle = mResult.mRootView.getResources()
                 .getDimensionPixelSize(R.dimen.freeform_resize_handle);
         int resize_corner = mResult.mRootView.getResources()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
new file mode 100644
index 0000000..0abe8ab
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.graphics.PointF;
+import android.view.MotionEvent;
+
+/**
+ * A detector for touch inputs that differentiates between drag and click inputs.
+ * All touch events must be passed through this class to track a drag event.
+ */
+public class DragDetector {
+    private int mTouchSlop;
+    private PointF mInputDownPoint;
+    private boolean mIsDragEvent;
+    private int mDragPointerId;
+    public DragDetector(int touchSlop) {
+        mTouchSlop = touchSlop;
+        mInputDownPoint = new PointF();
+        mIsDragEvent = false;
+        mDragPointerId = -1;
+    }
+
+    /**
+     * Determine if {@link MotionEvent} is part of a drag event.
+     * @return {@code true} if this is a drag event, {@code false} if not
+     */
+    public boolean detectDragEvent(MotionEvent ev) {
+        switch (ev.getAction()) {
+            case ACTION_DOWN: {
+                mDragPointerId = ev.getPointerId(0);
+                float rawX = ev.getRawX(0);
+                float rawY = ev.getRawY(0);
+                mInputDownPoint.set(rawX, rawY);
+                return false;
+            }
+            case ACTION_MOVE: {
+                if (!mIsDragEvent) {
+                    int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
+                    float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
+                    float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
+                    if (Math.hypot(dx, dy) > mTouchSlop) {
+                        mIsDragEvent = true;
+                    }
+                }
+                return mIsDragEvent;
+            }
+            case ACTION_UP: {
+                boolean result = mIsDragEvent;
+                mIsDragEvent = false;
+                mInputDownPoint.set(0, 0);
+                mDragPointerId = -1;
+                return result;
+            }
+            case ACTION_CANCEL: {
+                mIsDragEvent = false;
+                mInputDownPoint.set(0, 0);
+                mDragPointerId = -1;
+                return false;
+            }
+        }
+        return mIsDragEvent;
+    }
+
+    public void setTouchSlop(int touchSlop) {
+        mTouchSlop = touchSlop;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index b9f16b6..d3f1332 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -22,7 +22,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
 import android.content.Context;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.input.InputManager;
@@ -38,6 +37,7 @@
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.SurfaceControl;
+import android.view.ViewConfiguration;
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.view.BaseIWindow;
@@ -76,7 +76,7 @@
     private Rect mRightBottomCornerBounds;
 
     private int mDragPointerId = -1;
-    private int mTouchSlop;
+    private DragDetector mDragDetector;
 
     DragResizeInputListener(
             Context context,
@@ -115,6 +115,7 @@
         mInputEventReceiver = new TaskResizeInputEventReceiver(
                 mInputChannel, mHandler, mChoreographer);
         mCallback = callback;
+        mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
     }
 
     /**
@@ -146,7 +147,7 @@
         mHeight = height;
         mResizeHandleThickness = resizeHandleThickness;
         mCornerSize = cornerSize;
-        mTouchSlop = touchSlop;
+        mDragDetector.setTouchSlop(touchSlop);
 
         Region touchRegion = new Region();
         final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness);
@@ -228,7 +229,6 @@
         private boolean mConsumeBatchEventScheduled;
         private boolean mShouldHandleEvents;
         private boolean mDragging;
-        private final PointF mActionDownPoint = new PointF();
 
         private TaskResizeInputEventReceiver(
                 InputChannel inputChannel, Handler handler, Choreographer choreographer) {
@@ -276,7 +276,9 @@
             // Check if this is a touch event vs mouse event.
             // Touch events are tracked in four corners. Other events are tracked in resize edges.
             boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
-
+            if (isTouch) {
+                mDragging = mDragDetector.detectDragEvent(e);
+            }
             switch (e.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN: {
                     float x = e.getX(0);
@@ -290,7 +292,6 @@
                         mDragPointerId = e.getPointerId(0);
                         float rawX = e.getRawX(0);
                         float rawY = e.getRawY(0);
-                        mActionDownPoint.set(rawX, rawY);
                         int ctrlType = calculateCtrlType(isTouch, x, y);
                         mCallback.onDragResizeStart(ctrlType, rawX, rawY);
                         result = true;
@@ -304,14 +305,7 @@
                     int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                     float rawX = e.getRawX(dragPointerIndex);
                     float rawY = e.getRawY(dragPointerIndex);
-                    if (isTouch) {
-                        // Check for touch slop for touch events
-                        float dx = rawX - mActionDownPoint.x;
-                        float dy = rawY - mActionDownPoint.y;
-                        if (!mDragging && Math.hypot(dx, dy) > mTouchSlop) {
-                            mDragging = true;
-                        }
-                    } else {
+                    if (!isTouch) {
                         // For all other types allow immediate dragging.
                         mDragging = true;
                     }
@@ -323,14 +317,13 @@
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
-                    if (mDragging) {
+                    if (mShouldHandleEvents && mDragging) {
                         int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                         mCallback.onDragResizeEnd(
                                 e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex));
                     }
                     mDragging = false;
                     mShouldHandleEvents = false;
-                    mActionDownPoint.set(0, 0);
                     mDragPointerId = -1;
                     result = true;
                     break;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
index f0f2db7..a49a300 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
@@ -40,6 +40,9 @@
     private final Rect mTaskBoundsAtDragStart = new Rect();
     private final PointF mResizeStartPoint = new PointF();
     private final Rect mResizeTaskBounds = new Rect();
+    // Whether the |dragResizing| hint should be sent with the next bounds change WCT.
+    // Used to optimized fluid resizing of freeform tasks.
+    private boolean mPendingDragResizeHint = false;
 
     private int mCtrlType;
     private DragStartListener mDragStartListener;
@@ -53,6 +56,12 @@
 
     @Override
     public void onDragResizeStart(int ctrlType, float x, float y) {
+        if (ctrlType != CTRL_TYPE_UNDEFINED) {
+            // The task is being resized, send the |dragResizing| hint to core with the first
+            // bounds-change wct.
+            mPendingDragResizeHint = true;
+        }
+
         mDragStartListener.onDragStart(mWindowDecoration.mTaskInfo.taskId);
         mCtrlType = ctrlType;
 
@@ -63,19 +72,31 @@
 
     @Override
     public void onDragResizeMove(float x, float y) {
-        changeBounds(x, y);
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (changeBounds(wct, x, y)) {
+            if (mPendingDragResizeHint) {
+                // This is the first bounds change since drag resize operation started.
+                wct.setDragResizing(mWindowDecoration.mTaskInfo.token, true /* dragResizing */);
+                mPendingDragResizeHint = false;
+            }
+            mTaskOrganizer.applyTransaction(wct);
+        }
     }
 
     @Override
     public void onDragResizeEnd(float x, float y) {
-        changeBounds(x, y);
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.setDragResizing(mWindowDecoration.mTaskInfo.token, false /* dragResizing */);
+        changeBounds(wct, x, y);
+        mTaskOrganizer.applyTransaction(wct);
 
         mCtrlType = 0;
         mTaskBoundsAtDragStart.setEmpty();
         mResizeStartPoint.set(0, 0);
+        mPendingDragResizeHint = false;
     }
 
-    private void changeBounds(float x, float y) {
+    private boolean changeBounds(WindowContainerTransaction wct, float x, float y) {
         float deltaX = x - mResizeStartPoint.x;
         mResizeTaskBounds.set(mTaskBoundsAtDragStart);
         if ((mCtrlType & CTRL_TYPE_LEFT) != 0) {
@@ -96,10 +117,10 @@
         }
 
         if (!mResizeTaskBounds.isEmpty()) {
-            final WindowContainerTransaction wct = new WindowContainerTransaction();
             wct.setBounds(mWindowDecoration.mTaskInfo.token, mResizeTaskBounds);
-            mTaskOrganizer.applyTransaction(wct);
+            return true;
         }
+        return false;
     }
 
     interface DragStartListener {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 7cbace5..081c8ae 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -16,13 +16,9 @@
 
 package com.android.wm.shell;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -34,8 +30,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
@@ -44,11 +38,9 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.TaskInfo;
-import android.app.WindowConfiguration;
 import android.content.LocusId;
 import android.content.pm.ParceledListSlice;
 import android.os.Binder;
@@ -61,8 +53,6 @@
 import android.window.ITaskOrganizerController;
 import android.window.TaskAppearedInfo;
 import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransaction.Change;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -638,130 +628,10 @@
         verify(mTaskOrganizerController).restartTaskTopActivityProcessIfVisible(task1.token);
     }
 
-    @Test
-    public void testPrepareClearBoundsForStandardTasks() {
-        MockToken token1 = new MockToken();
-        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_UNDEFINED, token1);
-        mOrganizer.onTaskAppeared(task1, null);
-
-        MockToken token2 = new MockToken();
-        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_UNDEFINED, token2);
-        mOrganizer.onTaskAppeared(task2, null);
-
-        MockToken otherDisplayToken = new MockToken();
-        RunningTaskInfo otherDisplayTask = createTaskInfo(3, WINDOWING_MODE_UNDEFINED,
-                otherDisplayToken);
-        otherDisplayTask.displayId = 2;
-        mOrganizer.onTaskAppeared(otherDisplayTask, null);
-
-        WindowContainerTransaction wct = mOrganizer.prepareClearBoundsForStandardTasks(1);
-
-        assertEquals(wct.getChanges().size(), 2);
-        Change boundsChange1 = wct.getChanges().get(token1.binder());
-        assertNotNull(boundsChange1);
-        assertNotEquals(
-                (boundsChange1.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS), 0);
-        assertTrue(boundsChange1.getConfiguration().windowConfiguration.getBounds().isEmpty());
-
-        Change boundsChange2 = wct.getChanges().get(token2.binder());
-        assertNotNull(boundsChange2);
-        assertNotEquals(
-                (boundsChange2.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS), 0);
-        assertTrue(boundsChange2.getConfiguration().windowConfiguration.getBounds().isEmpty());
-    }
-
-    @Test
-    public void testPrepareClearBoundsForStandardTasks_onlyClearActivityTypeStandard() {
-        MockToken token1 = new MockToken();
-        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_UNDEFINED, token1);
-        mOrganizer.onTaskAppeared(task1, null);
-
-        MockToken token2 = new MockToken();
-        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_UNDEFINED, token2);
-        task2.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME);
-        mOrganizer.onTaskAppeared(task2, null);
-
-        WindowContainerTransaction wct = mOrganizer.prepareClearBoundsForStandardTasks(1);
-
-        // Only clear bounds for task1
-        assertEquals(1, wct.getChanges().size());
-        assertNotNull(wct.getChanges().get(token1.binder()));
-    }
-
-    @Test
-    public void testPrepareClearFreeformForStandardTasks() {
-        MockToken token1 = new MockToken();
-        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FREEFORM, token1);
-        mOrganizer.onTaskAppeared(task1, null);
-
-        MockToken token2 = new MockToken();
-        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_MULTI_WINDOW, token2);
-        mOrganizer.onTaskAppeared(task2, null);
-
-        MockToken otherDisplayToken = new MockToken();
-        RunningTaskInfo otherDisplayTask = createTaskInfo(3, WINDOWING_MODE_FREEFORM,
-                otherDisplayToken);
-        otherDisplayTask.displayId = 2;
-        mOrganizer.onTaskAppeared(otherDisplayTask, null);
-
-        WindowContainerTransaction wct = mOrganizer.prepareClearFreeformForStandardTasks(1);
-
-        // Only task with freeform windowing mode and the right display should be updated
-        assertEquals(wct.getChanges().size(), 1);
-        Change wmModeChange1 = wct.getChanges().get(token1.binder());
-        assertNotNull(wmModeChange1);
-        assertEquals(wmModeChange1.getWindowingMode(), WINDOWING_MODE_UNDEFINED);
-    }
-
-    @Test
-    public void testPrepareClearFreeformForStandardTasks_onlyClearActivityTypeStandard() {
-        MockToken token1 = new MockToken();
-        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FREEFORM, token1);
-        mOrganizer.onTaskAppeared(task1, null);
-
-        MockToken token2 = new MockToken();
-        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_FREEFORM, token2);
-        task2.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME);
-        mOrganizer.onTaskAppeared(task2, null);
-
-        WindowContainerTransaction wct = mOrganizer.prepareClearFreeformForStandardTasks(1);
-
-        // Only clear freeform for task1
-        assertEquals(1, wct.getChanges().size());
-        assertNotNull(wct.getChanges().get(token1.binder()));
-    }
-
     private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
         taskInfo.taskId = taskId;
         taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
         return taskInfo;
     }
-
-    private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode, MockToken token) {
-        RunningTaskInfo taskInfo = createTaskInfo(taskId, windowingMode);
-        taskInfo.displayId = 1;
-        taskInfo.token = token.token();
-        taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
-        return taskInfo;
-    }
-
-    private static class MockToken {
-        private final WindowContainerToken mToken;
-        private final IBinder mBinder;
-
-        MockToken() {
-            mToken = mock(WindowContainerToken.class);
-            mBinder = mock(IBinder.class);
-            when(mToken.asBinder()).thenReturn(mBinder);
-        }
-
-        WindowContainerToken token() {
-            return mToken;
-        }
-
-        IBinder binder() {
-            return mBinder;
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
index 79b520c..89bafcb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
@@ -16,10 +16,13 @@
 
 package com.android.wm.shell.desktopmode;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
@@ -30,13 +33,14 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -68,6 +72,9 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class DesktopModeControllerTest extends ShellTestCase {
@@ -83,9 +90,7 @@
     @Mock
     private Handler mMockHandler;
     @Mock
-    private Transitions mMockTransitions;
-    private TestShellExecutor mExecutor;
-
+    private Transitions mTransitions;
     private DesktopModeController mController;
     private DesktopModeTaskRepository mDesktopModeTaskRepository;
     private ShellInit mShellInit;
@@ -97,20 +102,19 @@
         when(DesktopModeStatus.isActive(any())).thenReturn(true);
 
         mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
-        mExecutor = new TestShellExecutor();
 
         mDesktopModeTaskRepository = new DesktopModeTaskRepository();
 
         mController = new DesktopModeController(mContext, mShellInit, mShellController,
-                mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mMockTransitions,
-                mDesktopModeTaskRepository, mMockHandler, mExecutor);
+                mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mTransitions,
+                mDesktopModeTaskRepository, mMockHandler, new TestShellExecutor());
 
-        when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(anyInt())).thenReturn(
-                new WindowContainerTransaction());
+        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>());
 
         mShellInit.init();
         clearInvocations(mShellTaskOrganizer);
         clearInvocations(mRootTaskDisplayAreaOrganizer);
+        clearInvocations(mTransitions);
     }
 
     @After
@@ -124,113 +128,133 @@
     }
 
     @Test
-    public void testDesktopModeEnabled_taskWmClearedDisplaySetToFreeform() {
-        // Create a fake WCT to simulate setting task windowing mode to undefined
-        WindowContainerTransaction taskWct = new WindowContainerTransaction();
-        MockToken taskMockToken = new MockToken();
-        taskWct.setWindowingMode(taskMockToken.token(), WINDOWING_MODE_UNDEFINED);
-        when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(
-                mContext.getDisplayId())).thenReturn(taskWct);
+    public void testDesktopModeEnabled_rootTdaSetToFreeform() {
+        DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
 
-        // Create a fake DisplayAreaInfo to check if windowing mode change is set correctly
-        MockToken displayMockToken = new MockToken();
-        DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(displayMockToken.mToken,
-                mContext.getDisplayId(), 0);
-        when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
-                .thenReturn(displayAreaInfo);
-
-        // The test
         mController.updateDesktopModeActive(true);
+        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
 
-        ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
-                WindowContainerTransaction.class);
-        verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
-
-        // WCT should have 2 changes - clear task wm mode and set display wm mode
-        WindowContainerTransaction wct = arg.getValue();
-        assertThat(wct.getChanges()).hasSize(2);
-
-        // Verify executed WCT has a change for setting task windowing mode to undefined
-        Change taskWmModeChange = wct.getChanges().get(taskMockToken.binder());
-        assertThat(taskWmModeChange).isNotNull();
-        assertThat(taskWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
-
-        // Verify executed WCT has a change for setting display windowing mode to freeform
-        Change displayWmModeChange = wct.getChanges().get(displayAreaInfo.token.asBinder());
-        assertThat(displayWmModeChange).isNotNull();
-        assertThat(displayWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
+        // 1 change: Root TDA windowing mode
+        assertThat(wct.getChanges().size()).isEqualTo(1);
+        // Verify WCT has a change for setting windowing mode to freeform
+        Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
+        assertThat(change).isNotNull();
+        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
     }
 
     @Test
-    public void testDesktopModeDisabled_taskWmAndBoundsClearedDisplaySetToFullscreen() {
-        // Create a fake WCT to simulate setting task windowing mode to undefined
-        WindowContainerTransaction taskWmWct = new WindowContainerTransaction();
-        MockToken taskWmMockToken = new MockToken();
-        taskWmWct.setWindowingMode(taskWmMockToken.token(), WINDOWING_MODE_UNDEFINED);
-        when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(
-                mContext.getDisplayId())).thenReturn(taskWmWct);
+    public void testDesktopModeDisabled_rootTdaSetToFullscreen() {
+        DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
 
-        // Create a fake WCT to simulate clearing task bounds
-        WindowContainerTransaction taskBoundsWct = new WindowContainerTransaction();
-        MockToken taskBoundsMockToken = new MockToken();
-        taskBoundsWct.setBounds(taskBoundsMockToken.token(), null);
-        when(mShellTaskOrganizer.prepareClearBoundsForStandardTasks(
-                mContext.getDisplayId())).thenReturn(taskBoundsWct);
-
-        // Create a fake DisplayAreaInfo to check if windowing mode change is set correctly
-        MockToken displayMockToken = new MockToken();
-        DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(displayMockToken.mToken,
-                mContext.getDisplayId(), 0);
-        when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
-                .thenReturn(displayAreaInfo);
-
-        // The test
         mController.updateDesktopModeActive(false);
+        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
 
-        ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
-                WindowContainerTransaction.class);
-        verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
+        // 1 change: Root TDA windowing mode
+        assertThat(wct.getChanges().size()).isEqualTo(1);
+        // Verify WCT has a change for setting windowing mode to fullscreen
+        Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
+        assertThat(change).isNotNull();
+        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
+    }
 
-        // WCT should have 3 changes - clear task wm mode and bounds and set display wm mode
-        WindowContainerTransaction wct = arg.getValue();
-        assertThat(wct.getChanges()).hasSize(3);
+    @Test
+    public void testDesktopModeEnabled_windowingModeCleared() {
+        createMockDisplayArea();
+        RunningTaskInfo freeformTask = createFreeformTask();
+        RunningTaskInfo fullscreenTask = createFullscreenTask();
+        RunningTaskInfo homeTask = createHomeTask();
+        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
+                Arrays.asList(freeformTask, fullscreenTask, homeTask)));
 
-        // Verify executed WCT has a change for setting task windowing mode to undefined
-        Change taskWmMode = wct.getChanges().get(taskWmMockToken.binder());
-        assertThat(taskWmMode).isNotNull();
-        assertThat(taskWmMode.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
+        mController.updateDesktopModeActive(true);
+        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
 
-        // Verify executed WCT has a change for clearing task bounds
-        Change bounds = wct.getChanges().get(taskBoundsMockToken.binder());
-        assertThat(bounds).isNotNull();
-        assertThat(bounds.getWindowSetMask() & WINDOW_CONFIG_BOUNDS).isNotEqualTo(0);
-        assertThat(bounds.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
+        // 2 changes: Root TDA windowing mode and 1 task
+        assertThat(wct.getChanges().size()).isEqualTo(2);
+        // No changes for tasks that are not standard or freeform
+        assertThat(wct.getChanges().get(fullscreenTask.token.asBinder())).isNull();
+        assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
+        // Standard freeform task has windowing mode cleared
+        Change change = wct.getChanges().get(freeformTask.token.asBinder());
+        assertThat(change).isNotNull();
+        assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
+    }
 
-        // Verify executed WCT has a change for setting display windowing mode to fullscreen
-        Change displayWmModeChange = wct.getChanges().get(displayAreaInfo.token.asBinder());
-        assertThat(displayWmModeChange).isNotNull();
-        assertThat(displayWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
+    @Test
+    public void testDesktopModeDisabled_windowingModeAndBoundsCleared() {
+        createMockDisplayArea();
+        RunningTaskInfo freeformTask = createFreeformTask();
+        RunningTaskInfo fullscreenTask = createFullscreenTask();
+        RunningTaskInfo homeTask = createHomeTask();
+        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
+                Arrays.asList(freeformTask, fullscreenTask, homeTask)));
+
+        mController.updateDesktopModeActive(false);
+        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
+
+        // 3 changes: Root TDA windowing mode and 2 tasks
+        assertThat(wct.getChanges().size()).isEqualTo(3);
+        // No changes to home task
+        assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
+        // Standard tasks have bounds cleared
+        assertThatBoundsCleared(wct.getChanges().get(freeformTask.token.asBinder()));
+        assertThatBoundsCleared(wct.getChanges().get(fullscreenTask.token.asBinder()));
+        // Freeform standard tasks have windowing mode cleared
+        assertThat(wct.getChanges().get(
+                freeformTask.token.asBinder()).getWindowingMode()).isEqualTo(
+                WINDOWING_MODE_UNDEFINED);
+    }
+
+    @Test
+    public void testDesktopModeEnabled_homeTaskBehindVisibleTask() {
+        createMockDisplayArea();
+        RunningTaskInfo fullscreenTask1 = createFullscreenTask();
+        fullscreenTask1.isVisible = true;
+        RunningTaskInfo fullscreenTask2 = createFullscreenTask();
+        fullscreenTask2.isVisible = false;
+        RunningTaskInfo homeTask = createHomeTask();
+        when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
+                Arrays.asList(fullscreenTask1, fullscreenTask2, homeTask)));
+
+        mController.updateDesktopModeActive(true);
+        WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
+
+        // Check that there are hierarchy changes for home task and visible task
+        assertThat(wct.getHierarchyOps()).hasSize(2);
+        // First show home task
+        WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
+        assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
+        assertThat(op1.getContainer()).isEqualTo(homeTask.token.asBinder());
+
+        // Then visible task on top of it
+        WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
+        assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
+        assertThat(op2.getContainer()).isEqualTo(fullscreenTask1.token.asBinder());
     }
 
     @Test
     public void testShowDesktopApps() {
         // Set up two active tasks on desktop
-        mDesktopModeTaskRepository.addActiveTask(1);
-        mDesktopModeTaskRepository.addActiveTask(2);
-        MockToken token1 = new MockToken();
-        MockToken token2 = new MockToken();
-        ActivityManager.RunningTaskInfo taskInfo1 = new TestRunningTaskInfoBuilder().setToken(
-                token1.token()).setLastActiveTime(100).build();
-        ActivityManager.RunningTaskInfo taskInfo2 = new TestRunningTaskInfoBuilder().setToken(
-                token2.token()).setLastActiveTime(200).build();
-        when(mShellTaskOrganizer.getRunningTaskInfo(1)).thenReturn(taskInfo1);
-        when(mShellTaskOrganizer.getRunningTaskInfo(2)).thenReturn(taskInfo2);
+        RunningTaskInfo freeformTask1 = createFreeformTask();
+        freeformTask1.lastActiveTime = 100;
+        RunningTaskInfo freeformTask2 = createFreeformTask();
+        freeformTask2.lastActiveTime = 200;
+        mDesktopModeTaskRepository.addActiveTask(freeformTask1.taskId);
+        mDesktopModeTaskRepository.addActiveTask(freeformTask2.taskId);
+        when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
+                freeformTask1);
+        when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
+                freeformTask2);
 
         // Run show desktop apps logic
         mController.showDesktopApps();
         ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(
                 WindowContainerTransaction.class);
-        verify(mShellTaskOrganizer).applyTransaction(wctCaptor.capture());
+        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+            verify(mTransitions).startTransition(eq(TRANSIT_TO_FRONT), wctCaptor.capture(), any());
+        } else {
+            verify(mShellTaskOrganizer).applyTransaction(wctCaptor.capture());
+        }
         WindowContainerTransaction wct = wctCaptor.getValue();
 
         // Check wct has reorder calls
@@ -239,12 +263,12 @@
         // Task 2 has activity later, must be first
         WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
         assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op1.getContainer()).isEqualTo(token2.binder());
+        assertThat(op1.getContainer()).isEqualTo(freeformTask2.token.asBinder());
 
         // Task 1 should be second
-        WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(0);
+        WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
         assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
-        assertThat(op2.getContainer()).isEqualTo(token2.binder());
+        assertThat(op2.getContainer()).isEqualTo(freeformTask1.token.asBinder());
     }
 
     @Test
@@ -266,7 +290,7 @@
 
     @Test
     public void testHandleTransitionRequest_notFreeform_returnsNull() {
-        ActivityManager.RunningTaskInfo trigger = new ActivityManager.RunningTaskInfo();
+        RunningTaskInfo trigger = new RunningTaskInfo();
         trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         WindowContainerTransaction wct = mController.handleRequest(
                 new Binder(),
@@ -276,7 +300,7 @@
 
     @Test
     public void testHandleTransitionRequest_returnsWct() {
-        ActivityManager.RunningTaskInfo trigger = new ActivityManager.RunningTaskInfo();
+        RunningTaskInfo trigger = new RunningTaskInfo();
         trigger.token = new MockToken().mToken;
         trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         WindowContainerTransaction wct = mController.handleRequest(
@@ -285,6 +309,57 @@
         assertThat(wct).isNotNull();
     }
 
+    private DisplayAreaInfo createMockDisplayArea() {
+        DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(new MockToken().mToken,
+                mContext.getDisplayId(), 0);
+        when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
+                .thenReturn(displayAreaInfo);
+        return displayAreaInfo;
+    }
+
+    private RunningTaskInfo createFreeformTask() {
+        return new TestRunningTaskInfoBuilder()
+                .setToken(new MockToken().token())
+                .setActivityType(ACTIVITY_TYPE_STANDARD)
+                .setWindowingMode(WINDOWING_MODE_FREEFORM)
+                .setLastActiveTime(100)
+                .build();
+    }
+
+    private RunningTaskInfo createFullscreenTask() {
+        return new TestRunningTaskInfoBuilder()
+                .setToken(new MockToken().token())
+                .setActivityType(ACTIVITY_TYPE_STANDARD)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .setLastActiveTime(100)
+                .build();
+    }
+
+    private RunningTaskInfo createHomeTask() {
+        return new TestRunningTaskInfoBuilder()
+                .setToken(new MockToken().token())
+                .setActivityType(ACTIVITY_TYPE_HOME)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .setLastActiveTime(100)
+                .build();
+    }
+
+    private WindowContainerTransaction getDesktopModeSwitchTransaction() {
+        ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
+                WindowContainerTransaction.class);
+        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+            verify(mTransitions).startTransition(eq(TRANSIT_CHANGE), arg.capture(), any());
+        } else {
+            verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
+        }
+        return arg.getValue();
+    }
+
+    private void assertThatBoundsCleared(Change change) {
+        assertThat((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) != 0).isTrue();
+        assertThat(change.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
+    }
+
     private static class MockToken {
         private final WindowContainerToken mToken;
         private final IBinder mBinder;
@@ -298,9 +373,5 @@
         WindowContainerToken token() {
             return mToken;
         }
-
-        IBinder binder() {
-            return mBinder;
-        }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index d01f3d3..38b75f8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -16,18 +16,24 @@
 
 package com.android.wm.shell.splitscreen;
 
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -35,6 +41,8 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -65,11 +73,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.Optional;
-
 /**
  * Tests for {@link SplitScreenController}
  */
@@ -91,18 +99,21 @@
     @Mock Transitions mTransitions;
     @Mock TransactionPool mTransactionPool;
     @Mock IconProvider mIconProvider;
-    @Mock Optional<RecentTasksController> mRecentTasks;
+    @Mock StageCoordinator mStageCoordinator;
+    @Mock RecentTasksController mRecentTasks;
+    @Captor ArgumentCaptor<Intent> mIntentCaptor;
 
     private SplitScreenController mSplitScreenController;
 
     @Before
     public void setup() {
+        assumeTrue(ActivityTaskManager.supportsSplitScreenMultiWindow(mContext));
         MockitoAnnotations.initMocks(this);
         mSplitScreenController = spy(new SplitScreenController(mContext, mShellInit,
                 mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
                 mRootTDAOrganizer, mDisplayController, mDisplayImeController,
                 mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
-                mIconProvider, mRecentTasks, mMainExecutor));
+                mIconProvider, mRecentTasks, mMainExecutor, mStageCoordinator));
     }
 
     @Test
@@ -148,58 +159,100 @@
     }
 
     @Test
-    public void testShouldAddMultipleTaskFlag_notInSplitScreen() {
-        doReturn(false).when(mSplitScreenController).isSplitScreenVisible();
-        doReturn(true).when(mSplitScreenController).isValidToEnterSplitScreen(any());
-
-        // Verify launching the same activity returns true.
+    public void testStartIntent_appendsNoUserActionFlag() {
         Intent startIntent = createStartIntent("startActivity");
-        ActivityManager.RunningTaskInfo focusTaskInfo =
-                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
-        doReturn(focusTaskInfo).when(mSplitScreenController).getFocusingTaskInfo();
-        assertTrue(mSplitScreenController.shouldAddMultipleTaskFlag(
-                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
 
-        // Verify launching different activity returns false.
-        Intent diffIntent = createStartIntent("diffActivity");
-        focusTaskInfo =
-                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, diffIntent);
-        doReturn(focusTaskInfo).when(mSplitScreenController).getFocusingTaskInfo();
-        assertFalse(mSplitScreenController.shouldAddMultipleTaskFlag(
-                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
+        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
+
+        verify(mStageCoordinator).startIntent(eq(pendingIntent), mIntentCaptor.capture(),
+                eq(SPLIT_POSITION_TOP_OR_LEFT), isNull());
+        assertEquals(FLAG_ACTIVITY_NO_USER_ACTION,
+                mIntentCaptor.getValue().getFlags() & FLAG_ACTIVITY_NO_USER_ACTION);
     }
 
     @Test
-    public void testShouldAddMultipleTaskFlag_inSplitScreen() {
-        doReturn(true).when(mSplitScreenController).isSplitScreenVisible();
+    public void startIntent_multiInstancesSupported_appendsMultipleTaskFag() {
+        doReturn(true).when(mSplitScreenController).supportMultiInstancesSplit(any());
         Intent startIntent = createStartIntent("startActivity");
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
+        // Put the same component into focus task
+        ActivityManager.RunningTaskInfo focusTaskInfo =
+                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
+        doReturn(focusTaskInfo).when(mStageCoordinator).getFocusingTaskInfo();
+        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
+
+        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
+
+        verify(mStageCoordinator).startIntent(eq(pendingIntent), mIntentCaptor.capture(),
+                eq(SPLIT_POSITION_TOP_OR_LEFT), isNull());
+        assertEquals(FLAG_ACTIVITY_MULTIPLE_TASK,
+                mIntentCaptor.getValue().getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK);
+    }
+
+    @Test
+    public void startIntent_multiInstancesSupported_startTaskInBackgroundBeforeSplitActivated() {
+        doReturn(true).when(mSplitScreenController).supportMultiInstancesSplit(any());
+        doNothing().when(mSplitScreenController).startTask(anyInt(), anyInt(), any());
+        Intent startIntent = createStartIntent("startActivity");
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
+        // Put the same component into focus task
+        ActivityManager.RunningTaskInfo focusTaskInfo =
+                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
+        doReturn(focusTaskInfo).when(mStageCoordinator).getFocusingTaskInfo();
+        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
+        // Put the same component into a task in the background
+        ActivityManager.RecentTaskInfo sameTaskInfo = new ActivityManager.RecentTaskInfo();
+        doReturn(sameTaskInfo).when(mRecentTasks).findTaskInBackground(any());
+
+        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
+
+        verify(mSplitScreenController).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
+                isNull());
+    }
+
+    @Test
+    public void startIntent_multiInstancesSupported_startTaskInBackgroundAfterSplitActivated() {
+        doReturn(true).when(mSplitScreenController).supportMultiInstancesSplit(any());
+        doNothing().when(mSplitScreenController).startTask(anyInt(), anyInt(), any());
+        Intent startIntent = createStartIntent("startActivity");
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
+        // Put the same component into another side of the split
+        doReturn(true).when(mSplitScreenController).isSplitScreenVisible();
         ActivityManager.RunningTaskInfo sameTaskInfo =
                 createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, startIntent);
-        Intent diffIntent = createStartIntent("diffActivity");
-        ActivityManager.RunningTaskInfo differentTaskInfo =
-                createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, diffIntent);
+        doReturn(sameTaskInfo).when(mSplitScreenController).getTaskInfo(
+                SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        // Put the same component into a task in the background
+        doReturn(new ActivityManager.RecentTaskInfo()).when(mRecentTasks)
+                .findTaskInBackground(any());
 
-        // Verify launching the same activity return false.
-        doReturn(sameTaskInfo).when(mSplitScreenController)
-                .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
-        assertFalse(mSplitScreenController.shouldAddMultipleTaskFlag(
-                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
+        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
 
-        // Verify launching the same activity as adjacent returns true.
-        doReturn(differentTaskInfo).when(mSplitScreenController)
-                .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
-        doReturn(sameTaskInfo).when(mSplitScreenController)
-                .getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
-        assertTrue(mSplitScreenController.shouldAddMultipleTaskFlag(
-                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
+        verify(mSplitScreenController).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
+                isNull());
+    }
 
-        // Verify launching different activity from adjacent returns false.
-        doReturn(differentTaskInfo).when(mSplitScreenController)
-                .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
-        doReturn(differentTaskInfo).when(mSplitScreenController)
-                .getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
-        assertFalse(mSplitScreenController.shouldAddMultipleTaskFlag(
-                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
+    @Test
+    public void startIntent_multiInstancesNotSupported_switchesPositionAfterSplitActivated() {
+        doReturn(false).when(mSplitScreenController).supportMultiInstancesSplit(any());
+        Intent startIntent = createStartIntent("startActivity");
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
+        // Put the same component into another side of the split
+        doReturn(true).when(mSplitScreenController).isSplitScreenVisible();
+        ActivityManager.RunningTaskInfo sameTaskInfo =
+                createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, startIntent);
+        doReturn(sameTaskInfo).when(mSplitScreenController).getTaskInfo(
+                SPLIT_POSITION_BOTTOM_OR_RIGHT);
+
+        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
+
+        verify(mStageCoordinator).switchSplitPosition(anyString());
     }
 
     private Intent createStartIntent(String activityName) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
new file mode 100644
index 0000000..ac10ddb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
@@ -0,0 +1,130 @@
+package com.android.wm.shell.windowdecor
+
+import android.app.ActivityManager
+import android.graphics.Rect
+import android.os.IBinder
+import android.testing.AndroidTestingRunner
+import android.window.WindowContainerToken
+import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_RIGHT
+import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_UNDEFINED
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+/**
+ * Tests for [TaskPositioner].
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:TaskPositionerTest
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TaskPositionerTest : ShellTestCase() {
+
+    @Mock
+    private lateinit var mockShellTaskOrganizer: ShellTaskOrganizer
+    @Mock
+    private lateinit var mockWindowDecoration: WindowDecoration<*>
+    @Mock
+    private lateinit var mockDragStartListener: TaskPositioner.DragStartListener
+
+    @Mock
+    private lateinit var taskToken: WindowContainerToken
+    @Mock
+    private lateinit var taskBinder: IBinder
+
+    private lateinit var taskPositioner: TaskPositioner
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        taskPositioner = TaskPositioner(
+                mockShellTaskOrganizer,
+                mockWindowDecoration,
+                mockDragStartListener
+        )
+        `when`(taskToken.asBinder()).thenReturn(taskBinder)
+        mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
+            taskId = TASK_ID
+            token = taskToken
+            configuration.windowConfiguration.bounds = STARTING_BOUNDS
+        }
+    }
+
+    @Test
+    fun testDragResize_move_skipsDragResizingFlag() {
+        taskPositioner.onDragResizeStart(
+                CTRL_TYPE_UNDEFINED, // Move
+                STARTING_BOUNDS.left.toFloat(),
+                STARTING_BOUNDS.top.toFloat()
+        )
+
+        // Move the task 10px to the right.
+        val newX = STARTING_BOUNDS.left.toFloat() + 10
+        val newY = STARTING_BOUNDS.top.toFloat()
+        taskPositioner.onDragResizeMove(
+                newX,
+                newY
+        )
+
+        taskPositioner.onDragResizeEnd(newX, newY)
+
+        verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder &&
+                        ((change.changeMask and CHANGE_DRAG_RESIZING) != 0) &&
+                        change.dragResizing
+            }
+        })
+    }
+
+    @Test
+    fun testDragResize_resize_setsDragResizingFlag() {
+        taskPositioner.onDragResizeStart(
+                CTRL_TYPE_RIGHT, // Resize right
+                STARTING_BOUNDS.left.toFloat(),
+                STARTING_BOUNDS.top.toFloat()
+        )
+
+        // Resize the task by 10px to the right.
+        val newX = STARTING_BOUNDS.right.toFloat() + 10
+        val newY = STARTING_BOUNDS.top.toFloat()
+        taskPositioner.onDragResizeMove(
+                newX,
+                newY
+        )
+
+        taskPositioner.onDragResizeEnd(newX, newY)
+
+        verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder &&
+                        ((change.changeMask and CHANGE_DRAG_RESIZING) != 0) &&
+                        change.dragResizing
+            }
+        })
+        verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder &&
+                        ((change.changeMask and CHANGE_DRAG_RESIZING) != 0) &&
+                        !change.dragResizing
+            }
+        })
+    }
+
+    companion object {
+        private const val TASK_ID = 5
+        private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
+    }
+}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 95599bd..1183ca3 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -174,6 +174,12 @@
     jfieldID typeId;
 } gDescriptorInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID ctorId;
+    jmethodID setId;
+} gBufferInfo;
+
 struct fields_t {
     jmethodID postEventFromNativeID;
     jmethodID lockAndGetContextID;
@@ -460,11 +466,7 @@
         return err;
     }
 
-    ScopedLocalRef<jclass> clazz(
-            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
-
-    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
-    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
+    env->CallVoidMethod(bufferInfo, gBufferInfo.setId, (jint)offset, (jint)size, timeUs, flags);
 
     return OK;
 }
@@ -1091,13 +1093,7 @@
             CHECK(msg->findInt64("timeUs", &timeUs));
             CHECK(msg->findInt32("flags", (int32_t *)&flags));
 
-            ScopedLocalRef<jclass> clazz(
-                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
-            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
-            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
-
-            obj = env->NewObject(clazz.get(), ctor);
-
+            obj = env->NewObject(gBufferInfo.clazz, gBufferInfo.ctorId);
             if (obj == NULL) {
                 if (env->ExceptionCheck()) {
                     ALOGE("Could not create MediaCodec.BufferInfo.");
@@ -1107,7 +1103,7 @@
                 return;
             }
 
-            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
+            env->CallVoidMethod(obj, gBufferInfo.setId, (jint)offset, (jint)size, timeUs, flags);
             break;
         }
 
@@ -3235,6 +3231,16 @@
 
     gDescriptorInfo.typeId = env->GetFieldID(clazz.get(), "mType", "I");
     CHECK(gDescriptorInfo.typeId != NULL);
+
+    clazz.reset(env->FindClass("android/media/MediaCodec$BufferInfo"));
+    CHECK(clazz.get() != NULL);
+    gBufferInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
+
+    gBufferInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
+    CHECK(gBufferInfo.ctorId != NULL);
+
+    gBufferInfo.setId = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
+    CHECK(gBufferInfo.setId != NULL);
 }
 
 static void android_media_MediaCodec_native_setup(
diff --git a/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml
new file mode 100644
index 0000000..46abff8
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml
@@ -0,0 +1,33 @@
+<!--
+     Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="22"
+    android:viewportHeight="17"
+    android:width="22dp"
+    android:height="17dp">
+  <group>
+    <group>
+      <path android:fillColor="#FF000000"
+          android:pathData="M1.03 8.47l0.43-4.96h4.33v1.17H2.48L2.25 7.39C2.66 7.1 3.1 6.96 3.57 6.96c0.77 0 1.38 0.3 1.83 0.9 s0.66 1.41 0.66 2.43c0 1.03-0.24 1.84-0.72 2.43S4.2 13.6 3.36 13.6c-0.75 0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07 0.57 0.23 1 0.49 1.29s0.59 0.43 1.01 0.43c0.47 0 0.84-0.2 1.1-0.61c0.26-0.41 0.4-0.96 0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.76 8.09 3.28 8.09c-0.4 0-0.72 0.1-0.96 0.31L1.99 8.73L1.03 8.47z"/>
+    </group>
+    <group>
+      <path android:fillColor="#FF000000"
+          android:pathData="M 18.93,5.74 L 18.93,3.39 L 17.63,3.39 L 17.63,5.74 L 15.28,5.74 L 15.28,7.04 L 17.63,7.04 L 17.63,9.39 L 18.93,9.39 L 18.93,7.04 L 21.28,7.04 L 21.28,5.74 z"/>
+    </group>
+    <path android:fillColor="#FF000000"
+        android:pathData="M13.78 12.24l-0.22 0.27c-0.63 0.73-1.55 1.1-2.76 1.1c-1.08 0-1.92-0.36-2.53-1.07s-0.93-1.72-0.94-3.02V7.56 c0-1.39 0.28-2.44 0.84-3.13s1.39-1.04 2.51-1.04c0.95 0 1.69 0.26 2.23 0.79s0.83 1.28 0.89 2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45s-0.74-0.52-1.34-0.52c-0.72 0-1.24 0.23-1.57 0.7S8.6 6.37 8.59 7.4v2.03c0 1 0.19 1.77 0.57 2.31 c0.38 0.54 0.93 0.8 1.65 0.8c0.67 0 1.19-0.16 1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+  </group>
+</vector>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 327e4e9..8a57232 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -86,7 +86,7 @@
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Use system selection (default)"</item>
+    <item msgid="2494959071796102843">"Use System Selection (Default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
     <item msgid="720249083677397051">"AAC"</item>
     <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
@@ -96,7 +96,7 @@
     <item msgid="506175145534048710">"Opus"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Use system selection (default)"</item>
+    <item msgid="8868109554557331312">"Use System Selection (Default)"</item>
     <item msgid="9024885861221697796">"SBC"</item>
     <item msgid="4688890470703790013">"AAC"</item>
     <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
@@ -106,52 +106,52 @@
     <item msgid="7940970833006181407">"Opus"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
-    <item msgid="926809261293414607">"Use system selection (default)"</item>
+    <item msgid="926809261293414607">"Use System Selection (Default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
     <item msgid="3208896645474529394">"48.0 kHz"</item>
     <item msgid="8420261949134022577">"88.2 kHz"</item>
     <item msgid="8887519571067543785">"96.0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
-    <item msgid="2284090879080331090">"Use system selection (default)"</item>
+    <item msgid="2284090879080331090">"Use System Selection (Default)"</item>
     <item msgid="1872276250541651186">"44.1 kHz"</item>
     <item msgid="8736780630001704004">"48.0 kHz"</item>
     <item msgid="7698585706868856888">"88.2 kHz"</item>
     <item msgid="8946330945963372966">"96.0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
-    <item msgid="2574107108483219051">"Use system selection (default)"</item>
+    <item msgid="2574107108483219051">"Use System Selection (Default)"</item>
     <item msgid="4671992321419011165">"16 bits/sample"</item>
     <item msgid="1933898806184763940">"24 bits/sample"</item>
     <item msgid="1212577207279552119">"32 bits/sample"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
-    <item msgid="9196208128729063711">"Use system selection (default)"</item>
+    <item msgid="9196208128729063711">"Use System Selection (Default)"</item>
     <item msgid="1084497364516370912">"16 bits/sample"</item>
     <item msgid="2077889391457961734">"24 bits/sample"</item>
     <item msgid="3836844909491316925">"32 bits/sample"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
-    <item msgid="3014194562841654656">"Use system selection (default)"</item>
+    <item msgid="3014194562841654656">"Use System Selection (Default)"</item>
     <item msgid="5982952342181788248">"Mono"</item>
     <item msgid="927546067692441494">"Stereo"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
-    <item msgid="1997302811102880485">"Use system selection (default)"</item>
+    <item msgid="1997302811102880485">"Use System Selection (Default)"</item>
     <item msgid="8005696114958453588">"Mono"</item>
     <item msgid="1333279807604675720">"Stereo"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
-    <item msgid="1241278021345116816">"Optimised for Audio Quality (990kbps/909kbps)"</item>
-    <item msgid="3523665555859696539">"Balanced Audio And Connection Quality (660 kbps/606 kbps)"</item>
-    <item msgid="886408010459747589">"Optimised for Connection Quality (330kbps/303kbps)"</item>
+    <item msgid="1241278021345116816">"Optimized for Audio Quality (990kbps/909kbps)"</item>
+    <item msgid="3523665555859696539">"Balanced Audio And Connection Quality (660kbps/606kbps)"</item>
+    <item msgid="886408010459747589">"Optimized for Connection Quality (330kbps/303kbps)"</item>
     <item msgid="3808414041654351577">"Best Effort (Adaptive Bit Rate)"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
-    <item msgid="804499336721569838">"Optimised for Audio Quality"</item>
-    <item msgid="7451422070435297462">"Balanced Audio and Connection Quality"</item>
-    <item msgid="6173114545795428901">"Optimised for Connection Quality"</item>
-    <item msgid="4349908264188040530">"Best effort (adaptive bit rate)"</item>
+    <item msgid="804499336721569838">"Optimized for Audio Quality"</item>
+    <item msgid="7451422070435297462">"Balanced Audio And Connection Quality"</item>
+    <item msgid="6173114545795428901">"Optimized for Connection Quality"</item>
+    <item msgid="4349908264188040530">"Best Effort (Adaptive Bit Rate)"</item>
   </string-array>
   <string-array name="bluetooth_audio_active_device_summaries">
     <item msgid="8019740759207729126"></item>
@@ -161,25 +161,25 @@
   </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="1191094707770726722">"Off"</item>
-    <item msgid="7839165897132179888">"64 K"</item>
-    <item msgid="2715700596495505626">"256 K"</item>
-    <item msgid="7099386891713159947">"1 M"</item>
-    <item msgid="6069075827077845520">"4 M"</item>
-    <item msgid="6078203297886482480">"8 M"</item>
+    <item msgid="7839165897132179888">"64K"</item>
+    <item msgid="2715700596495505626">"256K"</item>
+    <item msgid="7099386891713159947">"1M"</item>
+    <item msgid="6069075827077845520">"4M"</item>
+    <item msgid="6078203297886482480">"8M"</item>
   </string-array>
   <string-array name="select_logd_size_lowram_titles">
     <item msgid="1145807928339101085">"Off"</item>
-    <item msgid="4064786181089783077">"64 K"</item>
-    <item msgid="3052710745383602630">"256 K"</item>
-    <item msgid="3691785423374588514">"1 M"</item>
+    <item msgid="4064786181089783077">"64K"</item>
+    <item msgid="3052710745383602630">"256K"</item>
+    <item msgid="3691785423374588514">"1M"</item>
   </string-array>
   <string-array name="select_logd_size_summaries">
     <item msgid="409235464399258501">"Off"</item>
-    <item msgid="4195153527464162486">"64 K per log buffer"</item>
-    <item msgid="7464037639415220106">"256 K per log buffer"</item>
-    <item msgid="8539423820514360724">"1 M per log buffer"</item>
-    <item msgid="1984761927103140651">"4 M per log buffer"</item>
-    <item msgid="2983219471251787208">"8 M per log buffer"</item>
+    <item msgid="4195153527464162486">"64K per log buffer"</item>
+    <item msgid="7464037639415220106">"256K per log buffer"</item>
+    <item msgid="8539423820514360724">"1M per log buffer"</item>
+    <item msgid="1984761927103140651">"4M per log buffer"</item>
+    <item msgid="2983219471251787208">"8M per log buffer"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
     <item msgid="704720725704372366">"Off"</item>
@@ -222,7 +222,7 @@
   </string-array>
   <string-array name="overlay_display_devices_entries">
     <item msgid="4497393944195787240">"None"</item>
-    <item msgid="8461943978957133391">"480 p"</item>
+    <item msgid="8461943978957133391">"480p"</item>
     <item msgid="6923083594932909205">"480p (secure)"</item>
     <item msgid="1226941831391497335">"720p"</item>
     <item msgid="7051983425968643928">"720p (secure)"</item>
@@ -258,10 +258,10 @@
   <string-array name="app_process_limit_entries">
     <item msgid="794656271086646068">"Standard limit"</item>
     <item msgid="8628438298170567201">"No background processes"</item>
-    <item msgid="915752993383950932">"At most, 1 process"</item>
-    <item msgid="8554877790859095133">"At most, 2 processes"</item>
-    <item msgid="9060830517215174315">"At most, 3 processes"</item>
-    <item msgid="6506681373060736204">"At most, 4 processes"</item>
+    <item msgid="915752993383950932">"At most 1 process"</item>
+    <item msgid="8554877790859095133">"At most 2 processes"</item>
+    <item msgid="9060830517215174315">"At most 3 processes"</item>
+    <item msgid="6506681373060736204">"At most 4 processes"</item>
   </string-array>
   <string-array name="usb_configuration_titles">
     <item msgid="3358668781763928157">"Charging"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index d991312..9b0c6b2a 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -46,22 +46,22 @@
     <string name="wifi_security_passpoint" msgid="2209078477216565387">"Passpoint"</string>
     <string name="wifi_security_sae" msgid="3644520541721422843">"WPA3-Personal"</string>
     <string name="wifi_security_psk_sae" msgid="8135104122179904684">"WPA2/WPA3-Personal"</string>
-    <string name="wifi_security_none_owe" msgid="5241745828327404101">"None/Enhanced open"</string>
-    <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced open"</string>
+    <string name="wifi_security_none_owe" msgid="5241745828327404101">"None/Enhanced Open"</string>
+    <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced Open"</string>
     <string name="wifi_security_eap_suiteb" msgid="415842785991698142">"WPA3-Enterprise 192-bit"</string>
     <string name="wifi_remembered" msgid="3266709779723179188">"Saved"</string>
     <string name="wifi_disconnected" msgid="7054450256284661757">"Disconnected"</string>
     <string name="wifi_disabled_generic" msgid="2651916945380294607">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP Configuration Failure"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Not connected due to low quality network"</string>
-    <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Wi-Fi Connection Failure"</string>
+    <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Authentication problem"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Can\'t connect"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Can\'t connect to \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Check password and try again"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Not in range"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Won\'t automatically connect"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"No Internet access"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"No internet access"</string>
     <string name="saved_network" msgid="7143698034077223645">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_to_metered_access_point" msgid="9179693207918156341">"Connected to metered network"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatically connected via %1$s"</string>
@@ -70,27 +70,27 @@
     <string name="connected_via_app" msgid="3532267661404276584">"Connected via <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="available_via_passpoint" msgid="1716000261192603682">"Available via %1$s"</string>
     <string name="tap_to_sign_up" msgid="5356397741063740395">"Tap to sign up"</string>
-    <string name="wifi_connected_no_internet" msgid="5087420713443350646">"No Internet"</string>
+    <string name="wifi_connected_no_internet" msgid="5087420713443350646">"No internet"</string>
     <string name="private_dns_broken" msgid="1984159464346556931">"Private DNS server cannot be accessed"</string>
     <string name="wifi_limited_connection" msgid="1184778285475204682">"Limited connection"</string>
-    <string name="wifi_status_no_internet" msgid="3799933875988829048">"No Internet"</string>
-    <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Sign-in required"</string>
+    <string name="wifi_status_no_internet" msgid="3799933875988829048">"No internet"</string>
+    <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Sign in required"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Access point temporarily full"</string>
     <string name="connected_via_carrier" msgid="1968057009076191514">"Connected via %1$s"</string>
     <string name="available_via_carrier" msgid="465598683092718294">"Available via %1$s"</string>
     <string name="osu_opening_provider" msgid="4318105381295178285">"Opening <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
     <string name="osu_connect_failed" msgid="9107873364807159193">"Couldn’t connect"</string>
     <string name="osu_completing_sign_up" msgid="8412636665040390901">"Completing sign-up…"</string>
-    <string name="osu_sign_up_failed" msgid="5605453599586001793">"Couldn’t complete sign-up. Tap to try again"</string>
+    <string name="osu_sign_up_failed" msgid="5605453599586001793">"Couldn’t complete sign-up. Tap to try again."</string>
     <string name="osu_sign_up_complete" msgid="7640183358878916847">"Sign-up complete. Connecting…"</string>
-    <string name="speed_label_very_slow" msgid="8526005255731597666">"Very slow"</string>
+    <string name="speed_label_very_slow" msgid="8526005255731597666">"Very Slow"</string>
     <string name="speed_label_slow" msgid="6069917670665664161">"Slow"</string>
     <string name="speed_label_okay" msgid="1253594383880810424">"OK"</string>
     <string name="speed_label_medium" msgid="9078405312828606976">"Medium"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Fast"</string>
-    <string name="speed_label_very_fast" msgid="8215718029533182439">"Very fast"</string>
+    <string name="speed_label_very_fast" msgid="8215718029533182439">"Very Fast"</string>
     <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expired"</string>
-    <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
+    <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Disconnected"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Disconnecting…"</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"Connecting…"</string>
@@ -120,8 +120,8 @@
     <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
-    <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
-    <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
+    <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text Messages"</string>
+    <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Access"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD audio"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Hearing Aids"</string>
@@ -130,14 +130,14 @@
     <string name="bluetooth_le_audio_profile_summary_connected" msgid="6916226974453480650">"Connected to LE audio"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Connected to media audio"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Connected to phone audio"</string>
-    <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Connected to file-transfer server"</string>
+    <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Connected to file transfer server"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"Connected to map"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"Connected to SAP"</string>
-    <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Not connected to file-transfer server"</string>
+    <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Not connected to file transfer server"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Connected to input device"</string>
-    <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Connected to device for Internet access"</string>
-    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Sharing local Internet connection with device"</string>
-    <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Use for Internet access"</string>
+    <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Connected to device for internet access"</string>
+    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Sharing local internet connection with device"</string>
+    <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Use for internet access"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="4453622103977592583">"Use for map"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"Use for SIM access"</string>
     <string name="bluetooth_a2dp_profile_summary_use_for" msgid="7324694226276491807">"Use for media audio"</string>
@@ -156,17 +156,17 @@
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Pairing rejected by <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computer"</string>
     <string name="bluetooth_talkback_headset" msgid="3406852564400882682">"Headset"</string>
-    <string name="bluetooth_talkback_phone" msgid="868393783858123880">"Telephone"</string>
+    <string name="bluetooth_talkback_phone" msgid="868393783858123880">"Phone"</string>
     <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string>
     <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string>
     <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string>
     <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string>
-    <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi off."</string>
-    <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi disconnected."</string>
-    <string name="accessibility_wifi_one_bar" msgid="6025652717281815212">"Wi-Fi one bar."</string>
-    <string name="accessibility_wifi_two_bars" msgid="687800024970972270">"Wi-Fi two bars."</string>
-    <string name="accessibility_wifi_three_bars" msgid="779895671061950234">"Wi-Fi three bars."</string>
-    <string name="accessibility_wifi_signal_full" msgid="7165262794551355617">"Wi-Fi signal full."</string>
+    <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi off."</string>
+    <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi disconnected."</string>
+    <string name="accessibility_wifi_one_bar" msgid="6025652717281815212">"Wifi one bar."</string>
+    <string name="accessibility_wifi_two_bars" msgid="687800024970972270">"Wifi two bars."</string>
+    <string name="accessibility_wifi_three_bars" msgid="779895671061950234">"Wifi three bars."</string>
+    <string name="accessibility_wifi_signal_full" msgid="7165262794551355617">"Wifi signal full."</string>
     <string name="accessibility_wifi_security_type_none" msgid="162352241518066966">"Open network"</string>
     <string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"Secure network"</string>
     <string name="process_kernel_label" msgid="950292573930336765">"Android OS"</string>
@@ -188,7 +188,7 @@
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Speech rate"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"Speed at which the text is spoken"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"Pitch"</string>
-    <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Affects the tone of the synthesised speech"</string>
+    <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Affects the tone of the synthesized speech"</string>
     <string name="tts_default_lang_title" msgid="4698933575028098940">"Language"</string>
     <string name="tts_lang_use_system" msgid="6312945299804012406">"Use system language"</string>
     <string name="tts_lang_not_selected" msgid="7927823081096056147">"Language not selected"</string>
@@ -198,7 +198,7 @@
     <string name="tts_install_data_title" msgid="1829942496472751703">"Install voice data"</string>
     <string name="tts_install_data_summary" msgid="3608874324992243851">"Install the voice data required for speech synthesis"</string>
     <string name="tts_engine_security_warning" msgid="3372432853837988146">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string>
-    <string name="tts_engine_network_required" msgid="8722087649733906851">"This language requires a working network connection for Text-to-Speech output."</string>
+    <string name="tts_engine_network_required" msgid="8722087649733906851">"This language requires a working network connection for text-to-speech output."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"This is an example of speech synthesis"</string>
     <string name="tts_status_title" msgid="8190784181389278640">"Default language status"</string>
     <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string>
@@ -234,7 +234,7 @@
     <string name="apn_settings_not_available" msgid="1147111671403342300">"Access Point Name settings are not available for this user"</string>
     <string name="enable_adb" msgid="8072776357237289039">"USB debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode when USB is connected"</string>
-    <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorisations"</string>
+    <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorizations"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless debugging"</string>
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode when Wi‑Fi is connected"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
@@ -243,22 +243,22 @@
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Pair device with QR code"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Pair new devices using QR code scanner"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pair device with pairing code"</string>
-    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six-digit code"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six digit code"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Paired devices"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Currently connected"</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Device details"</string>
     <string name="adb_device_forget" msgid="193072400783068417">"Forget"</string>
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Device fingerprint: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connection unsuccessful"</string>
-    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure that <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Pair with device"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi pairing code"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pairing unsuccessful"</string>
-    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure that the device is connected to the same network."</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure the device is connected to the same network."</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address and port"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; Port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
@@ -278,28 +278,28 @@
     <string name="mock_location_app_set" msgid="4706722469342913843">"Mock location app: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="debug_networking_category" msgid="6829757985772659599">"Networking"</string>
     <string name="wifi_display_certification" msgid="1805579519992520381">"Wireless display certification"</string>
-    <string name="wifi_verbose_logging" msgid="1785910450009679371">"Enable Wi‑Fi verbose logging"</string>
+    <string name="wifi_verbose_logging" msgid="1785910450009679371">"Enable Wi‑Fi Verbose Logging"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi scan throttling"</string>
-    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi‑Fi non‑persistent MAC randomisation"</string>
+    <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi‑Fi non‑persistent MAC randomization"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"Mobile data always active"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering hardware acceleration"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Show Bluetooth devices without names"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disable absolute volume"</string>
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
-    <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
+    <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
-    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP version"</string>
-    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP version"</string>
-    <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP Version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP Version"</string>
+    <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
-    <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
+    <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Sample Rate"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Trigger Bluetooth Audio Codec\nSelection: Sample Rate"</string>
-    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Grey-out means not supported by phone or headset"</string>
-    <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth audio bits per sample"</string>
+    <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Gray-out means not supported by phone or headset"</string>
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Bluetooth Audio Bits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Trigger Bluetooth Audio Codec\nSelection: Bits Per Sample"</string>
-    <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth audio channel mode"</string>
+    <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Bluetooth Audio Channel Mode"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Trigger Bluetooth Audio Codec\nSelection: Channel Mode"</string>
-    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Bluetooth audio LDAC codec: Playback quality"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Bluetooth Audio LDAC Codec: Playback Quality"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"Trigger Bluetooth Audio LDAC\nCodec Selection: Playback Quality"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"Private DNS"</string>
@@ -311,14 +311,14 @@
     <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Couldn\'t connect"</string>
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Show options for wireless display certification"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
-    <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduces battery drain and improves network performance"</string>
-    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"When this mode is enabled, this device’s MAC address may change each time that it connects to a network that has MAC randomisation enabled."</string>
+    <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduces battery drain &amp; improves network performance"</string>
+    <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"When this mode is enabled, this device’s MAC address may change each time it connects to a network that has MAC randomization enabled."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"Metered"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Unmetered"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"Logger buffer sizes"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Select Logger sizes per log buffer"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Clear logger persistent storage?"</string>
-    <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"When we are no longer monitoring with the persistent logger, we are required to erase the logger data resident on your device."</string>
+    <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"When we no longer are monitoring with the persistent logger, we are required to erase the logger data resident on your device."</string>
     <string name="select_logpersist_title" msgid="447071974007104196">"Store logger data persistently on device"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Select log buffers to store persistently on device"</string>
     <string name="select_usb_configuration_title" msgid="6339801314922294586">"Select USB Configuration"</string>
@@ -329,22 +329,22 @@
     <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Use tethering hardware acceleration if available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Allow USB debugging?"</string>
-    <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string>
+    <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
     <string name="adbwifi_warning_title" msgid="727104571653031865">"Allow wireless debugging?"</string>
     <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
-    <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string>
+    <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you’ve previously authorized?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Allow development settings?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string>
     <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verify apps over USB"</string>
-    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
+    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behavior."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
     <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Enables the Bluetooth Gabeldorsche feature stack."</string>
-    <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Enables the enhanced connectivity feature."</string>
+    <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Enables the Enhanced Connectivity feature."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
-    <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Set HDCP checking behaviour"</string>
+    <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Set HDCP checking behavior"</string>
     <string name="debug_debugging_category" msgid="535341063709248842">"Debugging"</string>
     <string name="debug_app" msgid="8903350241392391766">"Select debug app"</string>
     <string name="debug_app_not_set" msgid="1934083001283807188">"No debug application set"</string>
@@ -373,7 +373,7 @@
     <string name="debug_hw_overdraw" msgid="8944851091008756796">"Debug GPU overdraw"</string>
     <string name="disable_overlays" msgid="4206590799671557143">"Disable HW overlays"</string>
     <string name="disable_overlays_summary" msgid="1954852414363338166">"Always use GPU for screen compositing"</string>
-    <string name="simulate_color_space" msgid="1206503300335835151">"Simulate colour space"</string>
+    <string name="simulate_color_space" msgid="1206503300335835151">"Simulate color space"</string>
     <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Enable OpenGL traces"</string>
     <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Disable USB audio routing"</string>
     <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Disable automatic routing to USB audio peripherals"</string>
@@ -389,31 +389,31 @@
     <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Enable GPU debug layers"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Allow loading GPU debug layers for debug apps"</string>
     <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Enable verbose vendor logging"</string>
-    <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Include additional device-specific vendor logs in bug reports, which may contain private information, use more battery and/or use more storage."</string>
+    <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Include additional device-specific vendor logs in bug reports, which may contain private information, use more battery, and/or use more storage."</string>
     <string name="window_animation_scale_title" msgid="5236381298376812508">"Window animation scale"</string>
     <string name="transition_animation_scale_title" msgid="1278477690695439337">"Transition animation scale"</string>
     <string name="animator_duration_scale_title" msgid="7082913931326085176">"Animator duration scale"</string>
     <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simulate secondary displays"</string>
     <string name="debug_applications_category" msgid="5394089406638954196">"Apps"</string>
-    <string name="immediately_destroy_activities" msgid="1826287490705167403">"Don\'t keep activities"</string>
+    <string name="immediately_destroy_activities" msgid="1826287490705167403">"Don’t keep activities"</string>
     <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Destroy every activity as soon as the user leaves it"</string>
     <string name="app_process_limit_title" msgid="8361367869453043007">"Background process limit"</string>
     <string name="show_all_anrs" msgid="9160563836616468726">"Show background ANRs"</string>
-    <string name="show_all_anrs_summary" msgid="8562788834431971392">"Display App Not Responding dialogue for background apps"</string>
+    <string name="show_all_anrs_summary" msgid="8562788834431971392">"Display App Not Responding dialog for background apps"</string>
     <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Show notification channel warnings"</string>
     <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Displays on-screen warning when an app posts a notification without a valid channel"</string>
     <string name="force_allow_on_external" msgid="9187902444231637880">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
-    <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizeable"</string>
-    <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
+    <string name="force_resizable_activities" msgid="7143612144399959606">"Force activities to be resizable"</string>
+    <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string>
     <string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
     <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Enable support for experimental freeform windows."</string>
     <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
     <string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
-    <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
+    <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string>
     <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
     <string name="local_backup_password_toast_success" msgid="4891666204428091604">"New backup password set"</string>
-    <string name="local_backup_password_toast_confirmation_mismatch" msgid="2994718182129097733">"New password and confirmation don\'t match"</string>
+    <string name="local_backup_password_toast_confirmation_mismatch" msgid="2994718182129097733">"New password and confirmation don’t match"</string>
     <string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"Failure setting backup password"</string>
     <string name="loading_injected_setting_summary" msgid="8394446285689070348">"Loading…"</string>
   <string-array name="color_mode_names">
@@ -422,9 +422,9 @@
     <item msgid="6564241960833766170">"Standard"</item>
   </string-array>
   <string-array name="color_mode_descriptions">
-    <item msgid="6828141153199944847">"Enhanced colours"</item>
-    <item msgid="4548987861791236754">"Natural colours as seen by the eye"</item>
-    <item msgid="1282170165150762976">"Colours optimised for digital content"</item>
+    <item msgid="6828141153199944847">"Enhanced colors"</item>
+    <item msgid="4548987861791236754">"Natural colors as seen by the eye"</item>
+    <item msgid="1282170165150762976">"Colors optimized for digital content"</item>
   </string-array>
     <string name="inactive_apps_title" msgid="5372523625297212320">"Standby apps"</string>
     <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactive. Tap to toggle."</string>
@@ -441,15 +441,15 @@
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
     <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Set WebView implementation"</string>
     <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"This choice is no longer valid. Try again."</string>
-    <string name="picture_color_mode" msgid="1013807330552931903">"Picture colour mode"</string>
+    <string name="picture_color_mode" msgid="1013807330552931903">"Picture color mode"</string>
     <string name="picture_color_mode_desc" msgid="151780973768136200">"Use sRGB"</string>
     <string name="daltonizer_mode_disabled" msgid="403424372812399228">"Disabled"</string>
     <string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"Monochromacy"</string>
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomaly (red-green)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
-    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Colour correction can be helpful when you want to:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;See colours more accurately&lt;/li&gt; &lt;li&gt;&amp;nbsp;Remove colours to help you focus&lt;/li&gt; &lt;/ol&gt;"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Color correction"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Color correction can be helpful when you want to:&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;See colors more accurately&lt;/li&gt; &lt;li&gt;&amp;nbsp;Remove colors to help you focus&lt;/li&gt; &lt;/ol&gt;"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
@@ -476,7 +476,7 @@
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Device may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
-    <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
+    <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
     <string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
@@ -487,9 +487,9 @@
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string>
     <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string>
-    <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string>
+    <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully Charged"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string>
-    <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string>
+    <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by Restricted Setting"</string>
     <string name="disabled" msgid="8017887509554714950">"Disabled"</string>
     <string name="external_source_trusted" msgid="1146522036773132905">"Allowed"</string>
     <string name="external_source_untrusted" msgid="5037891688911672227">"Not allowed"</string>
@@ -515,13 +515,13 @@
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"Active input methods"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"Use system languages"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
-    <string name="ime_security_warning" msgid="6547562217880551450">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
+    <string name="ime_security_warning" msgid="6547562217880551450">"This input method may be able to collect all the text you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"Note: After a reboot, this app can\'t start until you unlock your phone"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS registration state"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"Registered"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Not registered"</string>
     <string name="status_unavailable" msgid="5279036186589861608">"Unavailable"</string>
-    <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC is randomised"</string>
+    <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC is randomized"</string>
     <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 device connected}=1{1 device connected}other{# devices connected}}"</string>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"More time."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Less time."</string>
@@ -530,7 +530,7 @@
     <string name="done" msgid="381184316122520313">"Done"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarms and reminders"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Allow setting alarms and reminders"</string>
-    <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
+    <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms &amp; reminders"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
@@ -549,7 +549,7 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
-    <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
+    <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off &amp; back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
     <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
@@ -558,23 +558,23 @@
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"There is no shared data for this user."</string>
     <string name="shared_data_query_failure_text" msgid="3489828881998773687">"There was an error fetching shared data. Try again."</string>
     <string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
-    <string name="blob_expires_text" msgid="7882727111491739331">"Expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+    <string name="blob_expires_text" msgid="7882727111491739331">"Expires at <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"There was an error deleting the shared data."</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"There are no leases acquired for this shared data. Would you like to delete it?"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
     <string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
-    <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires at <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
-    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure that you want to delete this shared data?"</string>
+    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure you want to delete this shared data?"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
     <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
-    <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customise with apps, wallpaper and so on. Users can also adjust device settings such as Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+    <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customize with apps, wallpaper, and so on. Users can also adjust device settings like Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
-    <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure that the person is available to take the device and set up their space."</string>
+    <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure the person is available to take the device and set up their space"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
     <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
@@ -583,7 +583,7 @@
     <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
     <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
-    <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
+    <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you’ll need to set up a screen lock to protect your apps and personal data."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
     <string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string>
     <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string>
@@ -626,7 +626,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string>
-    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
     <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
     <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
     <string name="carrier_network_change_mode" msgid="4257621815706644026">"Carrier network changing"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 4ef4ee6..20e8db6 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -184,7 +184,7 @@
     <string name="launch_defaults_some" msgid="3631650616557252926">"कुछ डिफ़ॉल्‍ट सेट हैं"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"कोई डिफ़ॉल्‍ट सेट नहीं है"</string>
     <string name="tts_settings" msgid="8130616705989351312">"लेख से बोली सेटिंग"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"लिखाई को बोली में बदलना"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"लिखाई को बोली में बदलने की सुविधा"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"बोली दर"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"बोलने की गति तय करें"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"पिच"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 7e65fa0..928ebc3 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -49,9 +49,9 @@
     <item msgid="1999413958589971747">"Unngår dårlig tilkobling midlertidig"</item>
   </string-array>
   <string-array name="hdcp_checking_titles">
-    <item msgid="2377230797542526134">"Kontrollér aldri"</item>
-    <item msgid="3919638466823112484">"Kontrollér kun DRM-innhold"</item>
-    <item msgid="9048424957228926377">"Kontrollér alltid"</item>
+    <item msgid="2377230797542526134">"Kontroller aldri"</item>
+    <item msgid="3919638466823112484">"Kontroller kun DRM-innhold"</item>
+    <item msgid="9048424957228926377">"Kontroller alltid"</item>
   </string-array>
   <string-array name="hdcp_checking_summaries">
     <item msgid="4045840870658484038">"Bruk aldri HDCP-kontroll"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 16ee8b8..4e3be22 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -437,7 +437,7 @@
     <string name="transcode_notification" msgid="5560515979793436168">"Vis omkodingsvarsler"</string>
     <string name="transcode_disable_cache" msgid="3160069309377467045">"Slå av omkodingsbuffer"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string>
-    <string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string>
+    <string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontroller tjenester som kjører"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Angi WebView-implementering"</string>
     <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Dette valget er ikke gyldig lenger. Prøv på nytt."</string>
diff --git a/packages/SettingsLib/res/values/carrierid_icon_overrides.xml b/packages/SettingsLib/res/values/carrierid_icon_overrides.xml
new file mode 100644
index 0000000..d2ae52d
--- /dev/null
+++ b/packages/SettingsLib/res/values/carrierid_icon_overrides.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!--
+  ~ This resource file exists to enumerate all network type icon overrides on a
+  ~ per-carrierId basis
+-->
+<resources>
+    <!--
+    Network type (RAT) icon overrides can be configured here on a per-carrierId basis.
+        1. Add a new TypedArray here, using the naming scheme below
+        2. The entries are (NetworkType, drawable ID) pairs
+        3. Add this array's ID to the MAPPING field of MobileIconCarrierIdOverrides.kt
+    -->
+    <array name="carrierId_2032_iconOverrides">
+        <item>5G_PLUS</item>
+        <item>@drawable/ic_5g_plus_mobiledata_default</item>
+    </array>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index 5fa04f9..faea5b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -412,14 +412,13 @@
     }
 
     companion object {
-        private const val TAG = "ThemedBatteryDrawable"
-        private const val WIDTH = 12f
-        private const val HEIGHT = 20f
+        const val WIDTH = 12f
+        const val HEIGHT = 20f
         private const val CRITICAL_LEVEL = 15
         // On a 12x20 grid, how wide to make the fill protection stroke.
         // Scales when our size changes
         private const val PROTECTION_STROKE_WIDTH = 3f
         // Arbitrarily chosen for visibility at small sizes
-        private const val PROTECTION_MIN_STROKE_WIDTH = 6f
+        const val PROTECTION_MIN_STROKE_WIDTH = 6f
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt
new file mode 100644
index 0000000..a0395b5
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.mobile
+
+import android.annotation.DrawableRes
+import android.content.res.Resources
+import android.content.res.TypedArray
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import com.android.settingslib.R
+import com.android.settingslib.SignalIcon.MobileIconGroup
+
+/**
+ * This class defines a network type (3G, 4G, etc.) override mechanism on a per-carrierId basis.
+ *
+ * Traditionally, carrier-customized network type iconography was achieved using the `MCC/MNC`
+ * resource qualifiers, and swapping out the drawable resource by name. It would look like this:
+ *
+ *     res/
+ *       drawable/
+ *         3g_mobiledata_icon.xml
+ *       drawable-MCC-MNC/
+ *         3g_mobiledata_icon.xml
+ *
+ * This would mean that, provided a context created with this MCC/MNC configuration set, loading
+ * the network type icon through [MobileIconGroup] would provide a carrier-defined network type
+ * icon rather than the AOSP-defined default.
+ *
+ * The MCC/MNC mechanism no longer can fully define carrier-specific network type icons, because
+ * there is no longer a 1:1 mapping between MCC/MNC and carrier. With the advent of MVNOs, multiple
+ * carriers can have the same MCC/MNC value, but wish to differentiate based on their carrier ID.
+ * CarrierId is a newer concept than MCC/MNC, and provides more granularity when it comes to
+ * determining the carrier (e.g. MVNOs can share MCC/MNC values with the network owner), therefore
+ * it can fit all of the same use cases currently handled by `MCC/MNC`, without the need to apply a
+ * configuration context in order to get the proper UI for a given SIM icon.
+ *
+ * NOTE: CarrierId icon overrides will always take precedence over those defined using `MCC/MNC`
+ * resource qualifiers.
+ *
+ * [MAPPING] encodes the relationship between CarrierId and the corresponding override array
+ * that exists in the config.xml. An alternative approach could be to generate the resource name
+ * by string concatenation at run-time:
+ *
+ *    val resName = "carrierId_$carrierId_iconOverrides"
+ *    val override = resources.getResourceIdentifier(resName)
+ *
+ * However, that's going to be far less efficient until MAPPING grows to a sufficient size. For now,
+ * given a relatively small number of entries, we should just maintain the mapping here.
+ */
+interface MobileIconCarrierIdOverrides {
+    @DrawableRes
+    fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int
+    fun carrierIdEntryExists(carrierId: Int): Boolean
+}
+
+class MobileIconCarrierIdOverridesImpl : MobileIconCarrierIdOverrides {
+    @DrawableRes
+    override fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int {
+        val resId = MAPPING[carrierId] ?: return 0
+        val ta = resources.obtainTypedArray(resId)
+        val map = parseNetworkIconOverrideTypedArray(ta)
+        ta.recycle()
+        return map[networkType] ?: 0
+    }
+
+    override fun carrierIdEntryExists(carrierId: Int) =
+        overrideExists(carrierId, MAPPING)
+
+    companion object {
+        private const val TAG = "MobileIconOverrides"
+        /**
+         * This map maintains the lookup from the canonical carrier ID (see below link) to the
+         * corresponding overlay resource. New overrides should add an entry below in order to
+         * change the network type icon resources based on carrier ID
+         *
+         * Refer to the link below for the canonical mapping maintained in AOSP:
+         * https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb
+         */
+        private val MAPPING = mapOf(
+            // 2032 == Xfinity Mobile
+            2032 to R.array.carrierId_2032_iconOverrides,
+        )
+
+        /**
+         * Parse `carrierId_XXXX_iconOverrides` for a particular network type. The resource file
+         * "carrierid_icon_overrides.xml" defines a TypedArray format for overriding specific
+         * network type icons (a.k.a. RAT icons) for a particular carrier ID. The format is defined
+         * as an array of (network type name, drawable) pairs:
+         *    <array name="carrierId_XXXX_iconOverrides>
+         *        <item>NET_TYPE_1</item>
+         *        <item>@drawable/net_type_1_override</item>
+         *        <item>NET_TYPE_2</item>
+         *        <item>@drawable/net_type_2_override</item>
+         *    </array>
+         *
+         * @param ta the [TypedArray] defined in carrierid_icon_overrides.xml
+         * @return the overridden drawable resource ID if it exists, or 0 if it does not
+         */
+        @VisibleForTesting
+        @JvmStatic
+        fun parseNetworkIconOverrideTypedArray(ta: TypedArray): Map<String, Int> {
+            if (ta.length() % 2 != 0) {
+                Log.w(TAG,
+                    "override must contain an even number of (key, value) entries. skipping")
+
+                return mapOf()
+            }
+
+            val result = mutableMapOf<String, Int>()
+            // The array is defined as Pair(String, resourceId), so walk by 2
+            for (i in 0 until ta.length() step 2) {
+                val key = ta.getString(i)
+                val override = ta.getResourceId(i + 1, 0)
+                if (key == null || override == 0) {
+                    Log.w(TAG, "Invalid override found. Skipping")
+                    continue
+                }
+                result[key] = override
+            }
+
+            return result
+        }
+
+        @JvmStatic
+        private fun overrideExists(carrierId: Int, mapping: Map<Int, Int>): Boolean =
+            mapping.containsKey(carrierId)
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java
new file mode 100644
index 0000000..740261d
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.mobile;
+
+import static com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl.parseNetworkIconOverrideTypedArray;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.res.TypedArray;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Map;
+
+@RunWith(RobolectricTestRunner.class)
+public final class MobileIconCarrierIdOverridesTest {
+    private static final String OVERRIDE_ICON_1_NAME = "name_1";
+    private static final int OVERRIDE_ICON_1_RES = 1;
+
+    private static final String OVERRIDE_ICON_2_NAME = "name_2";
+    private static final int OVERRIDE_ICON_2_RES = 2;
+
+    NetworkOverrideTypedArrayMock mResourceMock;
+
+    @Before
+    public void setUp() {
+        mResourceMock = new NetworkOverrideTypedArrayMock(
+                new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME },
+                new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES }
+        );
+    }
+
+    @Test
+    public void testParse_singleOverride() {
+        mResourceMock.setOverrides(
+                new String[] { OVERRIDE_ICON_1_NAME },
+                new int[] { OVERRIDE_ICON_1_RES }
+        );
+
+        Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
+
+        assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES);
+    }
+
+    @Test
+    public void testParse_multipleOverrides() {
+        mResourceMock.setOverrides(
+                new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME },
+                new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES }
+        );
+
+        Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
+
+        assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isEqualTo(OVERRIDE_ICON_2_RES);
+        assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES);
+    }
+
+    @Test
+    public void testParse_nonexistentKey_isNull() {
+        mResourceMock.setOverrides(
+                new String[] { OVERRIDE_ICON_1_NAME },
+                new int[] { OVERRIDE_ICON_1_RES }
+        );
+
+        Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
+
+        assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isNull();
+    }
+
+    static class NetworkOverrideTypedArrayMock {
+        private Object[] mInterleaved;
+
+        private final TypedArray mMockTypedArray = mock(TypedArray.class);
+
+        NetworkOverrideTypedArrayMock(
+                String[] networkTypes,
+                int[] iconOverrides) {
+
+            mInterleaved = interleaveTypes(networkTypes, iconOverrides);
+
+            doAnswer(invocation -> {
+                return mInterleaved[(int) invocation.getArgument(0)];
+            }).when(mMockTypedArray).getString(/* index */ anyInt());
+
+            doAnswer(invocation -> {
+                return mInterleaved[(int) invocation.getArgument(0)];
+            }).when(mMockTypedArray).getResourceId(/* index */ anyInt(), /* default */ anyInt());
+
+            when(mMockTypedArray.length()).thenAnswer(invocation -> {
+                return mInterleaved.length;
+            });
+        }
+
+        TypedArray getMock() {
+            return mMockTypedArray;
+        }
+
+        void setOverrides(String[] types, int[] resIds) {
+            mInterleaved = interleaveTypes(types, resIds);
+        }
+
+        private Object[] interleaveTypes(String[] strs, int[] ints) {
+            assertThat(strs.length).isEqualTo(ints.length);
+
+            Object[] ret = new Object[strs.length * 2];
+
+            // Keep track of where we are in the interleaved array, but iterate the overrides
+            int interleavedIndex = 0;
+            for (int i = 0; i < strs.length; i++) {
+                ret[interleavedIndex] = strs[i];
+                interleavedIndex += 1;
+                ret[interleavedIndex] = ints[i];
+                interleavedIndex += 1;
+            }
+            return ret;
+        }
+    }
+}
diff --git a/packages/Shell/res/values-en-rCA/strings.xml b/packages/Shell/res/values-en-rCA/strings.xml
index 5462813..65ab725 100644
--- a/packages/Shell/res/values-en-rCA/strings.xml
+++ b/packages/Shell/res/values-en-rCA/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Select to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Bug reports contain data from the system\'s various log files, which may include data that you consider sensitive (such as app-usage and location data). Only share bug reports with people and apps that you trust."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Bug reports contain data from the system\'s various log files, which may include data you consider sensitive (such as app-usage and location data). Only share bug reports with people and apps you trust."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Don\'t show again"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Bug report file could not be read"</string>
diff --git a/packages/SimAppDialog/res/values-en-rCA/strings.xml b/packages/SimAppDialog/res/values-en-rCA/strings.xml
index 1ddbaf9..7983c04 100644
--- a/packages/SimAppDialog/res/values-en-rCA/strings.xml
+++ b/packages/SimAppDialog/res/values-en-rCA/strings.xml
@@ -17,7 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="8898068901680117589">"Sim app dialogue"</string>
+    <string name="app_name" msgid="8898068901680117589">"Sim App Dialog"</string>
     <string name="install_carrier_app_title" msgid="334729104862562585">"Activate mobile service"</string>
     <string name="install_carrier_app_description" msgid="4014303558674923797">"To get your new SIM working properly, you\'ll need to install the <xliff:g id="ID_1">%1$s</xliff:g> app"</string>
     <string name="install_carrier_app_description_default" msgid="7356830245205847840">"To get your new SIM working properly, you\'ll need to install the carrier app"</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4267ba2..68ff116 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -195,6 +195,9 @@
     <permission android:name="com.android.systemui.permission.FLAGS"
                 android:protectionLevel="signature" />
 
+    <permission android:name="android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Adding Quick Settings tiles -->
     <uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
 
@@ -976,5 +979,12 @@
                 <action android:name="com.android.systemui.action.DISMISS_VOLUME_PANEL_DIALOG" />
             </intent-filter>
         </receiver>
+
+        <provider
+            android:authorities="com.android.systemui.keyguard.quickaffordance"
+            android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
+            android:exported="true"
+            android:permission="android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
+            />
     </application>
 </manifest>
diff --git a/packages/SystemUI/compose/features/AndroidManifest.xml b/packages/SystemUI/compose/features/AndroidManifest.xml
index eada40e..278a89f 100644
--- a/packages/SystemUI/compose/features/AndroidManifest.xml
+++ b/packages/SystemUI/compose/features/AndroidManifest.xml
@@ -34,6 +34,11 @@
             android:enabled="false"
             tools:replace="android:authorities"
             tools:node="remove" />
+        <provider android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
+            android:authorities="com.android.systemui.test.keyguard.quickaffordance.disabled"
+            android:enabled="false"
+            tools:replace="android:authorities"
+            tools:node="remove" />
         <provider android:name="com.android.keyguard.clock.ClockOptionsProvider"
             android:authorities="com.android.systemui.test.keyguard.clock.disabled"
             android:enabled="false"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt
deleted file mode 100644
index 4d94bab..0000000
--- a/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.user.ui.compose
-
-import android.graphics.drawable.Drawable
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.heightIn
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material3.DropdownMenu
-import androidx.compose.material3.DropdownMenuItem
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.graphics.painter.ColorPainter
-import androidx.compose.ui.platform.LocalConfiguration
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.core.graphics.drawable.toBitmap
-import com.android.systemui.common.ui.compose.load
-import com.android.systemui.compose.SysUiOutlinedButton
-import com.android.systemui.compose.SysUiTextButton
-import com.android.systemui.compose.features.R
-import com.android.systemui.compose.theme.LocalAndroidColorScheme
-import com.android.systemui.user.ui.viewmodel.UserActionViewModel
-import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
-import com.android.systemui.user.ui.viewmodel.UserViewModel
-import java.lang.Integer.min
-import kotlin.math.ceil
-
-@Composable
-fun UserSwitcherScreen(
-    viewModel: UserSwitcherViewModel,
-    onFinished: () -> Unit,
-    modifier: Modifier = Modifier,
-) {
-    val isFinishRequested: Boolean by viewModel.isFinishRequested.collectAsState(false)
-    val users: List<UserViewModel> by viewModel.users.collectAsState(emptyList())
-    val maxUserColumns: Int by viewModel.maximumUserColumns.collectAsState(1)
-    val menuActions: List<UserActionViewModel> by viewModel.menu.collectAsState(emptyList())
-    val isOpenMenuButtonVisible: Boolean by viewModel.isOpenMenuButtonVisible.collectAsState(false)
-    val isMenuVisible: Boolean by viewModel.isMenuVisible.collectAsState(false)
-
-    UserSwitcherScreenStateless(
-        isFinishRequested = isFinishRequested,
-        users = users,
-        maxUserColumns = maxUserColumns,
-        menuActions = menuActions,
-        isOpenMenuButtonVisible = isOpenMenuButtonVisible,
-        isMenuVisible = isMenuVisible,
-        onMenuClosed = viewModel::onMenuClosed,
-        onOpenMenuButtonClicked = viewModel::onOpenMenuButtonClicked,
-        onCancelButtonClicked = viewModel::onCancelButtonClicked,
-        onFinished = {
-            onFinished()
-            viewModel.onFinished()
-        },
-        modifier = modifier,
-    )
-}
-
-@Composable
-private fun UserSwitcherScreenStateless(
-    isFinishRequested: Boolean,
-    users: List<UserViewModel>,
-    maxUserColumns: Int,
-    menuActions: List<UserActionViewModel>,
-    isOpenMenuButtonVisible: Boolean,
-    isMenuVisible: Boolean,
-    onMenuClosed: () -> Unit,
-    onOpenMenuButtonClicked: () -> Unit,
-    onCancelButtonClicked: () -> Unit,
-    onFinished: () -> Unit,
-    modifier: Modifier = Modifier,
-) {
-    LaunchedEffect(isFinishRequested) {
-        if (isFinishRequested) {
-            onFinished()
-        }
-    }
-
-    Box(
-        modifier =
-            modifier
-                .fillMaxSize()
-                .padding(
-                    horizontal = 60.dp,
-                    vertical = 40.dp,
-                ),
-    ) {
-        UserGrid(
-            users = users,
-            maxUserColumns = maxUserColumns,
-            modifier = Modifier.align(Alignment.Center),
-        )
-
-        Buttons(
-            menuActions = menuActions,
-            isOpenMenuButtonVisible = isOpenMenuButtonVisible,
-            isMenuVisible = isMenuVisible,
-            onMenuClosed = onMenuClosed,
-            onOpenMenuButtonClicked = onOpenMenuButtonClicked,
-            onCancelButtonClicked = onCancelButtonClicked,
-            modifier = Modifier.align(Alignment.BottomEnd),
-        )
-    }
-}
-
-@Composable
-private fun UserGrid(
-    users: List<UserViewModel>,
-    maxUserColumns: Int,
-    modifier: Modifier = Modifier,
-) {
-    Column(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        verticalArrangement = Arrangement.spacedBy(44.dp),
-        modifier = modifier,
-    ) {
-        val rowCount = ceil(users.size / maxUserColumns.toFloat()).toInt()
-        (0 until rowCount).forEach { rowIndex ->
-            Row(
-                horizontalArrangement = Arrangement.spacedBy(64.dp),
-                modifier = modifier,
-            ) {
-                val fromIndex = rowIndex * maxUserColumns
-                val toIndex = min(users.size, (rowIndex + 1) * maxUserColumns)
-                users.subList(fromIndex, toIndex).forEach { user ->
-                    UserItem(
-                        viewModel = user,
-                    )
-                }
-            }
-        }
-    }
-}
-
-@Composable
-private fun UserItem(
-    viewModel: UserViewModel,
-) {
-    val onClicked = viewModel.onClicked
-    Column(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        modifier =
-            if (onClicked != null) {
-                    Modifier.clickable { onClicked() }
-                } else {
-                    Modifier
-                }
-                .alpha(viewModel.alpha),
-    ) {
-        Box {
-            UserItemBackground(modifier = Modifier.align(Alignment.Center).size(222.dp))
-
-            UserItemIcon(
-                image = viewModel.image,
-                isSelectionMarkerVisible = viewModel.isSelectionMarkerVisible,
-                modifier = Modifier.align(Alignment.Center).size(222.dp)
-            )
-        }
-
-        // User name
-        val text = viewModel.name.load()
-        if (text != null) {
-            // We use the box to center-align the text vertically as that is not possible with Text
-            // alone.
-            Box(
-                modifier = Modifier.size(width = 222.dp, height = 48.dp),
-            ) {
-                Text(
-                    text = text,
-                    style = MaterialTheme.typography.titleLarge,
-                    color = colorResource(com.android.internal.R.color.system_neutral1_50),
-                    maxLines = 1,
-                    overflow = TextOverflow.Ellipsis,
-                    modifier = Modifier.align(Alignment.Center),
-                )
-            }
-        }
-    }
-}
-
-@Composable
-private fun UserItemBackground(
-    modifier: Modifier = Modifier,
-) {
-    Image(
-        painter = ColorPainter(LocalAndroidColorScheme.current.colorBackground),
-        contentDescription = null,
-        modifier = modifier.clip(CircleShape),
-    )
-}
-
-@Composable
-private fun UserItemIcon(
-    image: Drawable,
-    isSelectionMarkerVisible: Boolean,
-    modifier: Modifier = Modifier,
-) {
-    Image(
-        bitmap = image.toBitmap().asImageBitmap(),
-        contentDescription = null,
-        modifier =
-            if (isSelectionMarkerVisible) {
-                    // Draws a ring
-                    modifier.border(
-                        width = 8.dp,
-                        color = LocalAndroidColorScheme.current.colorAccentPrimary,
-                        shape = CircleShape,
-                    )
-                } else {
-                    modifier
-                }
-                .padding(16.dp)
-                .clip(CircleShape)
-    )
-}
-
-@Composable
-private fun Buttons(
-    menuActions: List<UserActionViewModel>,
-    isOpenMenuButtonVisible: Boolean,
-    isMenuVisible: Boolean,
-    onMenuClosed: () -> Unit,
-    onOpenMenuButtonClicked: () -> Unit,
-    onCancelButtonClicked: () -> Unit,
-    modifier: Modifier = Modifier,
-) {
-    Row(
-        modifier = modifier,
-    ) {
-        // Cancel button.
-        SysUiTextButton(
-            onClick = onCancelButtonClicked,
-        ) {
-            Text(stringResource(R.string.cancel))
-        }
-
-        // "Open menu" button.
-        if (isOpenMenuButtonVisible) {
-            Spacer(modifier = Modifier.width(8.dp))
-            // To properly use a DropdownMenu in Compose, we need to wrap the button that opens it
-            // and the menu itself in a Box.
-            Box {
-                SysUiOutlinedButton(
-                    onClick = onOpenMenuButtonClicked,
-                ) {
-                    Text(stringResource(R.string.add))
-                }
-                Menu(
-                    viewModel = menuActions,
-                    isMenuVisible = isMenuVisible,
-                    onMenuClosed = onMenuClosed,
-                )
-            }
-        }
-    }
-}
-
-@Composable
-private fun Menu(
-    viewModel: List<UserActionViewModel>,
-    isMenuVisible: Boolean,
-    onMenuClosed: () -> Unit,
-    modifier: Modifier = Modifier,
-) {
-    val maxItemWidth = LocalConfiguration.current.screenWidthDp.dp / 4
-    DropdownMenu(
-        expanded = isMenuVisible,
-        onDismissRequest = onMenuClosed,
-        modifier =
-            modifier.background(
-                color = MaterialTheme.colorScheme.inverseOnSurface,
-            ),
-    ) {
-        viewModel.forEachIndexed { index, action ->
-            MenuItem(
-                viewModel = action,
-                onClicked = { action.onClicked() },
-                topPadding =
-                    if (index == 0) {
-                        16.dp
-                    } else {
-                        0.dp
-                    },
-                bottomPadding =
-                    if (index == viewModel.size - 1) {
-                        16.dp
-                    } else {
-                        0.dp
-                    },
-                modifier = Modifier.sizeIn(maxWidth = maxItemWidth),
-            )
-        }
-    }
-}
-
-@Composable
-private fun MenuItem(
-    viewModel: UserActionViewModel,
-    onClicked: () -> Unit,
-    topPadding: Dp,
-    bottomPadding: Dp,
-    modifier: Modifier = Modifier,
-) {
-    val context = LocalContext.current
-    val density = LocalDensity.current
-
-    val icon =
-        remember(viewModel.iconResourceId) {
-            val drawable =
-                checkNotNull(AppCompatResources.getDrawable(context, viewModel.iconResourceId))
-            val size = with(density) { 20.dp.toPx() }.toInt()
-            drawable
-                .toBitmap(
-                    width = size,
-                    height = size,
-                )
-                .asImageBitmap()
-        }
-
-    DropdownMenuItem(
-        text = {
-            Text(
-                text = stringResource(viewModel.textResourceId),
-                style = MaterialTheme.typography.bodyMedium,
-            )
-        },
-        onClick = onClicked,
-        leadingIcon = {
-            Spacer(modifier = Modifier.width(10.dp))
-            Image(
-                bitmap = icon,
-                contentDescription = null,
-            )
-        },
-        modifier =
-            modifier
-                .heightIn(
-                    min = 56.dp,
-                )
-                .padding(
-                    start = 18.dp,
-                    end = 65.dp,
-                    top = topPadding,
-                    bottom = bottomPadding,
-                ),
-    )
-}
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 9f211c9..553b86b 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -16,7 +16,6 @@
 -packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
 -packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
 -packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
 -packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 89f5c2c..66e44b9 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -70,10 +70,10 @@
     }
 
     /** Optional method for dumping debug information */
-    fun dump(pw: PrintWriter) { }
+    fun dump(pw: PrintWriter) {}
 
     /** Optional method for debug logging */
-    fun setLogBuffer(logBuffer: LogBuffer) { }
+    fun setLogBuffer(logBuffer: LogBuffer) {}
 }
 
 /** Interface for a specific clock face version rendered by the clock */
@@ -88,40 +88,37 @@
 /** Events that should call when various rendering parameters change */
 interface ClockEvents {
     /** Call every time tick */
-    fun onTimeTick() { }
+    fun onTimeTick() {}
 
     /** Call whenever timezone changes */
-    fun onTimeZoneChanged(timeZone: TimeZone) { }
+    fun onTimeZoneChanged(timeZone: TimeZone) {}
 
     /** Call whenever the text time format changes (12hr vs 24hr) */
-    fun onTimeFormatChanged(is24Hr: Boolean) { }
+    fun onTimeFormatChanged(is24Hr: Boolean) {}
 
     /** Call whenever the locale changes */
-    fun onLocaleChanged(locale: Locale) { }
-
-    /** Call whenever font settings change */
-    fun onFontSettingChanged() { }
+    fun onLocaleChanged(locale: Locale) {}
 
     /** Call whenever the color palette should update */
-    fun onColorPaletteChanged(resources: Resources) { }
+    fun onColorPaletteChanged(resources: Resources) {}
 }
 
 /** Methods which trigger various clock animations */
 interface ClockAnimations {
     /** Runs an enter animation (if any) */
-    fun enter() { }
+    fun enter() {}
 
     /** Sets how far into AOD the device currently is. */
-    fun doze(fraction: Float) { }
+    fun doze(fraction: Float) {}
 
     /** Sets how far into the folding animation the device is. */
-    fun fold(fraction: Float) { }
+    fun fold(fraction: Float) {}
 
     /** Runs the battery animation (if any). */
-    fun charge() { }
+    fun charge() {}
 
     /** Move the clock, for example, if the notification tray appears in split-shade mode. */
-    fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) { }
+    fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {}
 
     /**
      * Whether this clock has a custom position update animation. If true, the keyguard will call
@@ -135,11 +132,26 @@
 /** Events that have specific data about the related face */
 interface ClockFaceEvents {
     /** Region Darkness specific to the clock face */
-    fun onRegionDarknessChanged(isDark: Boolean) { }
+    fun onRegionDarknessChanged(isDark: Boolean) {}
+
+    /**
+     * Call whenever font settings change. Pass in a target font size in pixels. The specific clock
+     * design is allowed to ignore this target size on a case-by-case basis.
+     */
+    fun onFontSettingChanged(fontSizePx: Float) {}
+
+    /**
+     * Target region information for the clock face. For small clock, this will match the bounds of
+     * the parent view mostly, but have a target height based on the height of the default clock.
+     * For large clocks, the parent view is the entire device size, but most clocks will want to
+     * render within the centered targetRect to avoid obstructing other elements. The specified
+     * targetRegion is relative to the parent view.
+     */
+    fun onTargetRegionChanged(targetRegion: Rect?) {}
 }
 
 /** Some data about a clock design */
 data class ClockMetadata(
     val clockId: ClockId,
-    val name: String
+    val name: String,
 )
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index c297149..b49afee 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -37,7 +37,6 @@
         android:id="@+id/lockscreen_clock_view_large"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
         android:clipChildren="false"
         android:visibility="gone" />
 
diff --git a/packages/SystemUI/res-keyguard/values-land/dimens.xml b/packages/SystemUI/res-keyguard/values-land/dimens.xml
index a4e7a5f..f1aa544 100644
--- a/packages/SystemUI/res-keyguard/values-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-land/dimens.xml
@@ -27,4 +27,6 @@
     <integer name="scaled_password_text_size">26</integer>
 
     <dimen name="bouncer_user_switcher_y_trans">@dimen/status_bar_height</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 0a55cf7..3861d98 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -124,6 +124,8 @@
     <dimen name="bouncer_user_switcher_item_padding_horizontal">12dp</dimen>
     <dimen name="bouncer_user_switcher_header_padding_end">44dp</dimen>
     <dimen name="bouncer_user_switcher_y_trans">0dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
 
     <!-- 2 * the margin + size should equal the plus_margin -->
     <dimen name="user_switcher_icon_large_margin">16dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index b86929e..04dffb6 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -25,11 +25,11 @@
     </style>
     <style name="Keyguard.TextView.EmergencyButton" parent="Theme.SystemUI">
         <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">16sp</item>
         <item name="android:background">@drawable/kg_emergency_button_background</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
-        <item name="android:paddingLeft">12dp</item>
-        <item name="android:paddingRight">12dp</item>
+        <item name="android:paddingLeft">26dp</item>
+        <item name="android:paddingRight">26dp</item>
         <item name="android:stateListAnimator">@null</item>
     </style>
     <style name="NumPadKey" parent="Theme.SystemUI">
diff --git a/packages/SystemUI/res-product/values-en-rCA/strings.xml b/packages/SystemUI/res-product/values-en-rCA/strings.xml
index 04e63f5..131c42a 100644
--- a/packages/SystemUI/res-product/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rCA/strings.xml
@@ -25,7 +25,7 @@
     <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"The device will soon turn off; press to keep it on."</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No SIM card in tablet."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No SIM card in phone."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes do not match"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes does not match"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
diff --git a/packages/SystemUI/res/drawable/ic_watch.xml b/packages/SystemUI/res/drawable/ic_watch.xml
new file mode 100644
index 0000000..8ff880c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_watch.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M16,0L8,0l-0.95,5.73C5.19,7.19 4,9.45 4,12s1.19,4.81 3.05,6.27L8,24
+        h8l0.96,-5.73C18.81,16.81 20,14.54 20,12s-1.19,-4.81 -3.04,-6.27L16,0z
+        M12,18c-3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6 6,2.69 6,6 -2.69,6 -6,6z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/internet_dialog_selected_effect.xml b/packages/SystemUI/res/drawable/internet_dialog_selected_effect.xml
new file mode 100644
index 0000000..8f6b4c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/internet_dialog_selected_effect.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <solid android:color="@android:color/white"/>
+            <corners android:radius="?android:attr/buttonCornerRadius"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 5b96159..f14be41 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -190,6 +190,11 @@
 
                 </LinearLayout>
 
+                <ViewStub android:id="@+id/secondary_mobile_network_stub"
+                  android:inflatedId="@+id/secondary_mobile_network_layout"
+                  android:layout="@layout/qs_dialog_secondary_mobile_network"
+                  style="@style/InternetDialog.Network"/>
+
                 <LinearLayout
                     android:id="@+id/turn_on_wifi_layout"
                     style="@style/InternetDialog.Network"
@@ -307,22 +312,15 @@
 
             <LinearLayout
                 android:id="@+id/see_all_layout"
-                android:layout_width="match_parent"
+                style="@style/InternetDialog.Network"
                 android:layout_height="64dp"
-                android:clickable="true"
-                android:focusable="true"
-                android:background="?android:attr/selectableItemBackground"
-                android:gravity="center_vertical|center_horizontal"
-                android:orientation="horizontal"
-                android:paddingStart="22dp"
-                android:paddingEnd="22dp">
+                android:paddingStart="20dp">
 
                 <FrameLayout
                     android:layout_width="24dp"
                     android:layout_height="24dp"
                     android:clickable="false"
-                    android:layout_gravity="center_vertical|start"
-                    android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
+                    android:layout_gravity="center_vertical|start">
                     <ImageView
                         android:id="@+id/arrow_forward"
                         android:src="@drawable/ic_arrow_forward"
diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml
index 9b8b611..530db0d 100644
--- a/packages/SystemUI/res/layout/media_session_view.xml
+++ b/packages/SystemUI/res/layout/media_session_view.xml
@@ -44,7 +44,7 @@
         android:background="@drawable/qs_media_outline_album_bg"
         />
 
-    <com.android.systemui.ripple.MultiRippleView
+    <com.android.systemui.surfaceeffects.ripple.MultiRippleView
         android:id="@+id/touch_ripple_view"
         android:layout_width="match_parent"
         android:layout_height="@dimen/qs_media_session_height_expanded"
@@ -53,6 +53,15 @@
         app:layout_constraintTop_toTopOf="@id/album_art"
         app:layout_constraintBottom_toBottomOf="@id/album_art" />
 
+    <com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
+        android:id="@+id/turbulence_noise_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_expanded"
+        app:layout_constraintStart_toStartOf="@id/album_art"
+        app:layout_constraintEnd_toEndOf="@id/album_art"
+        app:layout_constraintTop_toTopOf="@id/album_art"
+        app:layout_constraintBottom_toBottomOf="@id/album_art" />
+
     <!-- Guideline for output switcher -->
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/center_vertical_guideline"
diff --git a/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml b/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml
new file mode 100644
index 0000000..4592c5e
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/InternetDialog.Network">
+
+    <FrameLayout
+	android:layout_width="24dp"
+	android:layout_height="24dp"
+	android:clickable="false"
+	android:layout_gravity="center_vertical|start">
+	<ImageView
+	    android:id="@+id/secondary_signal_icon"
+	    android:autoMirrored="true"
+	    android:layout_width="wrap_content"
+	    android:layout_height="wrap_content"
+	    android:layout_gravity="center"/>
+    </FrameLayout>
+
+    <LinearLayout
+	android:layout_weight="1"
+	android:orientation="vertical"
+	android:clickable="false"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:gravity="start|center_vertical">
+	<TextView
+	    android:id="@+id/secondary_mobile_title"
+	    android:maxLines="1"
+	    style="@style/InternetDialog.NetworkTitle"/>
+	<TextView
+	    android:id="@+id/secondary_mobile_summary"
+	    style="@style/InternetDialog.NetworkSummary"/>
+    </LinearLayout>
+
+    <FrameLayout
+	android:layout_width="24dp"
+	android:layout_height="match_parent"
+	android:clickable="false"
+	android:layout_gravity="end|center_vertical"
+	android:gravity="center">
+	<ImageView
+	    android:id="@+id/secondary_settings_icon"
+	    android:src="@drawable/ic_settings_24dp"
+	    android:layout_width="24dp"
+	    android:layout_gravity="end|center_vertical"
+	    android:layout_height="wrap_content"/>
+    </FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_record_options.xml b/packages/SystemUI/res/layout/screen_record_options.xml
index a936914..d6c9e98 100644
--- a/packages/SystemUI/res/layout/screen_record_options.xml
+++ b/packages/SystemUI/res/layout/screen_record_options.xml
@@ -50,6 +50,7 @@
             android:importantForAccessibility="yes"/>
     </LinearLayout>
     <LinearLayout
+        android:id="@+id/show_taps"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index 8388b67..bafdb11 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -26,12 +26,12 @@
     android:fitsSystemWindows="true">
 
     <com.android.systemui.statusbar.BackDropView
-            android:id="@+id/backdrop"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:visibility="gone"
-            sysui:ignoreRightInset="true"
-            >
+        android:id="@+id/backdrop"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        sysui:ignoreRightInset="true"
+    >
         <ImageView android:id="@+id/backdrop_back"
                    android:layout_width="match_parent"
                    android:scaleType="centerCrop"
@@ -49,7 +49,7 @@
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
-        />
+    />
 
     <com.android.systemui.scrim.ScrimView
         android:id="@+id/scrim_notifications"
@@ -57,17 +57,17 @@
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
-        />
+    />
 
     <com.android.systemui.statusbar.LightRevealScrim
-            android:id="@+id/light_reveal_scrim"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" />
+        android:id="@+id/light_reveal_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
 
     <include layout="@layout/status_bar_expanded"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="invisible" />
+             android:layout_width="match_parent"
+             android:layout_height="match_parent"
+             android:visibility="invisible" />
 
     <include layout="@layout/brightness_mirror_container" />
 
diff --git a/packages/SystemUI/res/layout/wireless_charging_layout.xml b/packages/SystemUI/res/layout/wireless_charging_layout.xml
index 887e3e7..f1bc883 100644
--- a/packages/SystemUI/res/layout/wireless_charging_layout.xml
+++ b/packages/SystemUI/res/layout/wireless_charging_layout.xml
@@ -22,7 +22,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <com.android.systemui.ripple.RippleView
+    <com.android.systemui.surfaceeffects.ripple.RippleView
         android:id="@+id/wireless_charging_ripple"
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 5e82f6d..15423af 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Stembystand"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kodeskandeerder"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontsluit"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Toestel is gesluit"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skandeer tans gesig"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Stuur"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Kan nie gesig herken nie"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gebruik eerder vingerafdruk"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth gekoppel."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterypersentasie is onbekend."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aan."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> persent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> persent, ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor gegrond op jou gebruik"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery laai tans, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Sien alle kennisgewings"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter geaktiveer."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Luitoestel-vibreer."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Wanneer jy ’n program deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat in daardie program sigbaar is of daarin gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Gaan voort"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deel of neem ’n program op"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Laat hierdie app toe om te deel of op te neem?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Wanneer jy deel, opneem of uitsaai, het hierdie app toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Wanneer jy ’n app deel, opneem of uitsaai, het hierdie app toegang tot enigiets wat in daardie program sigbaar is of daarin gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Deur jou IT-admin geblokkeer"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Skermskote is deur toestelbeleid gedeaktiveer"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Vee alles uit"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Bestuur"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geskiedenis"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontsluit om te gebruik"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kon nie jou kaarte kry nie; probeer later weer"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Sluitskerminstellings"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skandeer QR-kode"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Jy sal nie jou volgende wekker <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Skakel mobiele data af?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Jy sal nie deur <xliff:g id="CARRIER">%s</xliff:g> toegang tot data of die internet hê nie. Internet sal net deur Wi-Fi beskikbaar wees."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"jou diensverskaffer"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Skakel weer oor na <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiele data sal nie outomaties op grond van beskikbaarheid oorskakel nie"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nee, dankie"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, skakel oor"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Instellings kan nie jou antwoord verifieer nie omdat \'n program \'n toestemmingversoek verberg."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Laat <xliff:g id="APP_0">%1$s</xliff:g> toe om <xliff:g id="APP_2">%2$s</xliff:g>-skyfies te wys?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Dit kan inligting van <xliff:g id="APP">%1$s</xliff:g> af lees"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tydelik gekoppel"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Swak verbinding"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data sal nie outomaties koppel nie"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding nie"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen ander netwerke beskikbaar nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index c0a23d9..6c9b07f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"የQR ኮድ መቃኛ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"የቅኝት ፊት"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ላክ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"መልክን መለየት አልተቻለም"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"በምትኩ የጣት አሻራን ይጠቀሙ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ብሉቱዝ ተያይዟል።"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"የባትሪ መቶኛ አይታወቅም።"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"የአውሮፕላን ሁነታ።"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ቪፒኤን በርቷል።"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ባትሪ <xliff:g id="PERCENTAGE">%1$s</xliff:g> በመቶ፣ በአጠቃቀምዎ ላይ በመመስረት <xliff:g id="TIME">%2$s</xliff:g> ገደማ ይቀራል"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ባትሪ ኃይል በመሙላት ላይ፣ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ሁሉንም ማሳወቂያዎች ይመልከቱ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter ነቅቷል።"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"የስልክ ጥሪ ይንዘር።"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"አንድን መተግበሪያ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ቀጥል"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"መተግበሪያ ያጋሩ ወይም ይቅረጹ"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ይህ መተግበሪያ እንዲያጋራ ወይም እንዲቀርጽ ይፈቀድለት?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ ይህ መተግበሪያ በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"አንድን መተግበሪያ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ ይህ መተግበሪያ በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ በይለፍ ቃላት፣ በክፍያ ዝርዝሮች፣ በመልዕክቶች ወይም በሌሎች ልዩ ጥንቃቄ የሚያስፈልጋቸው መረጃዎች ላይ ጥንቃቄ ያድርጉ።"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"በእርስዎ የአይቲ አስተዳዳሪ ታግዷል"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"የማያ ገጽ ቀረጻ በመሣሪያ መመሪያ ተሰናክሏል"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ሁሉንም አጽዳ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ያቀናብሩ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ታሪክ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ለማየት ይክፈቱ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"የገጽ መቆለፊያ ቅንብሮች"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR ኮድ ቃኝ"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"የተንቀሳቃሽ ስልክ ውሂብ ይጥፋ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"በ<xliff:g id="CARRIER">%s</xliff:g> በኩል የውሂብ ወይም የበይነመረቡ መዳረሻ አይኖረዎትም። በይነመረብ በWi-Fi በኩል ብቻ ነው የሚገኝ የሚሆነው።"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"የእርስዎ አገልግሎት አቅራቢ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"ወደ <xliff:g id="CARRIER">%s</xliff:g> ተመልሶ ይቀየር?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"የተንቀሳቃሽ ስልክ ውሂብ በተገኝነት መሰረት በራስ ሰር አይቀይርም"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"አይ አመሰግናለሁ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"አዎ፣ ቀይር"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"አንድ መተግበሪያ የፍቃድ ጥያቄ እያገደ ስለሆነ ቅንብሮች ጥያቄዎን ማረጋገጥ አይችሉም።"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> የ<xliff:g id="APP_2">%2$s</xliff:g> ቁራጮችን እንዲያሳይ ይፈቀድለት?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ከ<xliff:g id="APP">%1$s</xliff:g> የመጣ መረጃን ማንበብ ይችላል"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"በጊዜያዊነት ተገናኝቷል"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ደካማ ግንኙነት"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"የተንቀሳቃሽ ስልክ ውሂብ በራስ-ሰር አይገናኝም"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ግንኙነት የለም"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ሌላ አውታረ መረብ የሉም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7f1b3c9..384087b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"المساعد الصوتي"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"محفظة"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"الماسح الضوئي لرمز الاستجابة السريعة"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"فتح القفل"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"الجهاز مُقفل."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"مسح الوجه"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"إرسال"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"يتعذّر التعرّف على الوجه."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"يمكنك استخدام بصمة إصبعك."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"نسبة شحن البطارية غير معروفة."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"مستوى البطارية <xliff:g id="NUMBER">%d</xliff:g> في المائة."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"نسبة الشحن بالبطارية <xliff:g id="PERCENTAGE">%1$s</xliff:g> بالمائة، ويتبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا بناءً على استخدامك."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"جارٍ شحن البطارية، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"الاطّلاع على جميع الإشعارات"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"تم تفعيل المبرقة الكاتبة."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"رنين مع الاهتزاز."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثه، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> الوصول إلى كل العناصر المعروضة أو التي يتم تشغيلها في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"متابعة"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"مشاركة محتوى تطبيق أو تسجيله"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"هل تريد السماح لهذا التطبيق بمشاركة المحتوى أو تسجيله؟"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"أثناء مشاركة المحتوى أو تسجيله أو بثه، يمكن لهذا التطبيق الوصول إلى كل العناصر المرئية على شاشتك أو التي يتم تشغيلها على جهازك، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثه، يمكن لهذا التطبيق الوصول إلى كل العناصر المعروضة أو التي يتم تشغيلها في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"حظر مشرف تكنولوجيا المعلومات هذه الميزة"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ميزة \"تصوير الشاشة\" غير مفعَّلة بسبب سياسة الجهاز."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"محو الكل"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"إدارة"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"السجلّ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"فتح القفل للاستخدام"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"مسح رمز الاستجابة السريعة ضوئيًا"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"هل تريد إيقاف بيانات الجوّال؟"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"‏لن تتمكّن من استخدام البيانات أو الإنترنت من خلال <xliff:g id="CARRIER">%s</xliff:g>. ولن يتوفر اتصال الإنترنت إلا عبر Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"مشغّل شبكة الجوّال"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"هل تريد التبديل مرة أخرى إلى \"<xliff:g id="CARRIER">%s</xliff:g>\"؟"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"لن يتم تلقائيًا تبديل بيانات الجوّال بناءً على التوفّر."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"لا، شكرًا"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"نعم، أريد التبديل"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"لا يمكن للإعدادات التحقق من ردك لأن هناك تطبيقًا يحجب طلب الإذن."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"هل تريد السماح لتطبيق <xliff:g id="APP_0">%1$s</xliff:g> بعرض شرائح <xliff:g id="APP_2">%2$s</xliff:g>؟"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- يستطيع قراءة المعلومات من <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"متصلة مؤقتًا"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"الاتصال ضعيف"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"لن يتم تلقائيًا الاتصال ببيانات الجوّال."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"لا يتوفّر اتصال بالإنترنت"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"لا تتوفّر شبكات أخرى."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 5dfe17d..411419c 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ৱালেট"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"কিউআৰ ক’ড স্কেনাৰ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক কৰক"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইচটো লক হৈ আছে"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"চেহেৰা স্কেন কৰি থকা হৈছে"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"পঠিয়াওক"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"মুখাৱয়ব চিনিব নোৱাৰি"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ইয়াৰ সলনি ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"এয়াৰপ্লে’ন ম’ড।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ভিপিএন অন অৱস্থাত আছে।"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰী।"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰী <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰী চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"আটাইবোৰ জাননী চাওক"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter সক্ষম কৰা হ\'ল৷"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ৰিংগাৰ কম্পন অৱস্থাত আছে৷"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"অব্যাহত ৰাখক"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"এটা এপ্ শ্বেয়াৰ অথবা ৰেকৰ্ড কৰক"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"এই এপ্‌টোক শ্বেয়াৰ অথবা ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ এই এপ্‌টোৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ এই এপ্‌টোৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা অথবা অন্য সংবেদনশীল তথ্যৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"আপোনাৰ আইটি প্ৰশাসকে অৱৰোধ কৰিছে"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ডিভাইচ সম্পৰ্কীয় নীতিয়ে স্ক্ৰীন কেপশ্বাৰ কৰাটো অক্ষম কৰিছে"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"আটাইবোৰ মচক"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"পৰিচালনা"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্ৰীনৰ ছেটিং"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"কিউআৰ ক’ড স্কেন কৰক"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লে’ন ম’ড"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ম’বাইল ডেটা অফ কৰিবনে?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপুনি <xliff:g id="CARRIER">%s</xliff:g>ৰ জৰিয়তে ডেটা সংযোগ বা ইণ্টাৰনেট সংযোগ নাপাব। কেৱল ৱাই-ফাইৰ যোগেৰে ইণ্টাৰনেট উপলব্ধ হ\'ব।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"আপোনাৰ বাহক"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"আকৌ <xliff:g id="CARRIER">%s</xliff:g>লৈ সলনি কৰিবনে?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ম’বাইলৰ ডেটা উপলব্ধতাৰ ওপৰত ভিত্তি কৰি স্বয়ংক্ৰিয়ভাৱে সলনি কৰা নহ’ব"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"নালাগে, ধন্যবাদ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"হয়, সলনি কৰক"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"এটা এপে অনুমতি বিচাৰি কৰা অনুৰোধ এটা ঢাকি ধৰা বাবে ছেটিঙৰ পৰা আপোনাৰ উত্তৰ সত্যাপন কৰিব পৰা নাই।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>ক <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাবলৈ অনুমতি দিবনে?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ তথ্য পঢ়িব পাৰে"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"অস্থায়ীভাৱে সংযোগ কৰা হৈছে"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"বেয়া সংযোগ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ম’বাইল ডেটা স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"সংযোগ নাই"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index feab7f0..f3e281f 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Səs Yardımçısı"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Pulqabı"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR Kodu Skaneri"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Kiliddən çıxarın"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilidlənib"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Üzün skan edilməsi"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Göndərin"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Üzü tanımaq olmur"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmaq izi istifadə edin"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth qoşulub."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareyanın faizi naməlumdur."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçuş rejimi"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktivdir."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> faizdir."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya <xliff:g id="PERCENTAGE">%1$s</xliff:g> faizdir, istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batareya doldurulur, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%% faiz."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Bütün bildirişlərə baxın"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter aktivləşdirilib."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zəng vibrasiyası"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Paylaşdığınız, qeydə aldığınız və ya yayımladığınız zaman <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tətbiqi həmin tətbiqdə göstərilən və ya oxudulan hər şeyə giriş edə bilir. Odur ki, parollar, ödəniş detalları, mesajlar və ya digər həssas məlumatlarla bağlı diqqətli olun."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Davam edin"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Tətbiqi paylaşın və ya qeydə alın"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Bu tətbiqə paylaşmağa və ya yazmağa icazə verilsin?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Paylaşdığınız, yazdığınız və ya yayımladığınız zaman bu tətbiq ekranınızda görünən və ya cihazınızda oxudulan hər şeyə giriş edə bilir. Odur ki, parollar, ödəniş detalları, mesajlar və ya digər həssas məlumatlarla bağlı diqqətli olun."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Paylaşdığınız, qeydə aldığınız və ya yayımladığınız zaman bu tətbiq həmin tətbiqdə göstərilən və ya oxudulan hər şeyə giriş edə bilir. Odur ki, parollar, ödəniş detalları, mesajlar və ya digər həssas məlumatlarla bağlı diqqətli olun."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"İT admininiz tərəfindən bloklanıb"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ekran çəkimi cihaz siyasəti ilə deaktiv edilib"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hamısını silin"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"İdarə edin"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Tarixçə"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"İstifadə etmək üçün kiliddən çıxarın"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilid ekranı ayarları"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR kodu skanlayın"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobil data söndürülsün?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> ilə data və ya internetə daxil ola bilməyəcəksiniz. İnternet yalnız Wi-Fi ilə əlçatan olacaq."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operatorunuz"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> operatoruna keçirilsin?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobil data əlçatımlıq əsasında avtomatik olaraq keçirilməyəcək"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Xeyr, təşəkkürlər"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Bəli, keçirin"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Tətbiq icazə sorğusunu gizlətdiyi üçün Ayarlar cavabınızı doğrulaya bilməz."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> tətbiqinə <xliff:g id="APP_2">%2$s</xliff:g> hissələrini göstərmək üçün icazə verilsin?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> tətbiqindən məlumat oxuya bilər"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Müvəqqəti qoşulub"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Zəif bağlantı"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil data avtomatik qoşulmayacaq"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yoxdur"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Heç bir başqa şəbəkə əlçatan deyil"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index efed08f..0fc6331 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skener QR koda"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključajte"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Lice nije prepoznato"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je priključen."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procenat napunjenosti baterije nije poznat."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim rada u avionu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je uključen."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija je na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, preostalo vreme na osnovu korišćenja je <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> posto."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Pogledajte sva obaveštenja"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter je omogućen."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibracija zvona."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kada delite, snimate ili prebacujete aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Budite pažljivi sa lozinkama, informacijama o plaćanju, porukama ili drugim osetljivim informacijama."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Nastavi"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Delite ili snimite aplikaciju"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Želite da dozvolite ovoj aplikaciji da deli ili snima?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kada delite, snimate ili prebacujete, ova aplikacija ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Budite pažljivi sa lozinkama, informacijama o plaćanju, porukama ili drugim osetljivim informacijama."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kada delite, snimate ili prebacujete aplikaciju, ova aplikacija ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Budite pažljivi sa lozinkama, informacijama o plaćanju, porukama ili drugim osetljivim informacijama."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokira IT administrator"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Snimanje ekrana je onemogućeno smernicama za uređaj"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Obriši sve"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključaj radi korišćenja"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Podešavanja zaključanog ekrana"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skenirajte QR kôd"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Želite da isključite mobilne podatke?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ili internetu preko mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo preko WiFi veze."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"mobilni operater"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Želite da se vratite na mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilni podaci se neće automatski promeniti na osnovu dostupnosti"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, hvala"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Da, pređi"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Podešavanja ne mogu da verifikuju vaš odgovor jer aplikacija skriva zahtev za dozvolu."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Želite li da dozvolite aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isečke iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Može da čita podatke iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Veza je loša"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nije uspelo autom. povezivanje preko mob. podataka"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Veza nije uspostavljena"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index cc37204..85458bf 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Галасавая дапамога"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кашалёк"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Сканер QR-кодаў"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблакiраваць"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Прылада заблакіравана"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканіраванне твару"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Адправіць"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Твар не распазнаны"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скарыстайце адбітак пальца"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-сувязь."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Працэнт зараду акумулятара невядомы."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Рэжым палёту."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN уключана."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Працэнт зараду акумулятара: <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Зарад акумулятара ў працэнтах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Пры такім выкарыстанні яго хопіць прыблізна на <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Акумулятар зараджаецца. Бягучы зарад: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Паказаць усе апавяшчэнні"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter уключаны."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Выклік з вібрацыяй."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Калі пачынаецца абагульванне, запіс ці трансляцыя змесціва праграмы, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> атрымлівае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў і іншай канфідэнцыяльнай інфармацыі."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Далей"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Абагульванне або запіс праграмы"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Дазволіць гэтай праграме абагульваць або запісваць змесціва?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Калі пачынаецца абагульванне, запіс ці трансляцыя, гэта праграма атрымлівае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, звестак пра плацяжы, паведамленняў і іншай канфідэнцыяльнай інфармацыі."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Калі пачынаецца абагульванне, запіс ці трансляцыя змесціва праграмы, гэта праграма атрымлівае доступ да ўсяго змесціва, якое ў ёй паказваецца ці прайграецца. Таму прадухіліце паказ пароляў, звестак пра плацяжы, паведамленняў і іншай канфідэнцыяльнай інфармацыі."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Заблакіравана вашым ІТ-адміністратарам"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Здыманне экрана адключана згодна з палітыкай прылады"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Ачысціць усё"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Кіраваць"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Гісторыя"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблакіраваць для выкарыстання"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Налады экрана блакіроўкі"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Сканіраванне QR-кода"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Вы не пачуеце наступны будзільнік <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Выключыць мабільную перадачу даных?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"У вас не будзе доступу да даных ці інтэрнэту праз аператара <xliff:g id="CARRIER">%s</xliff:g>. Інтэрнэт будзе даступны толькі праз Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ваш аператар"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Зноў пераключыцца на аператара \"<xliff:g id="CARRIER">%s</xliff:g>\"?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мабільны інтэрнэт не будзе аўтаматычна пераключацца ў залежнасці ад даступнасці"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Не, дзякуй"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Так, пераключыцца"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Праграма хавае запыт на дазвол, таму ваш адказ немагчыма спраўдзіць у Наладах."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Дазволіць праграме <xliff:g id="APP_0">%1$s</xliff:g> паказваць зрэзы праграмы <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Можа счытваць інфармацыю з праграмы <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Падключана часова"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Нестабільнае падключэнне"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мабільная перадача даных не ўключаецца аўтаматычна"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма падключэння"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Больш няма даступных сетак"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 5a6ad73..44ee85c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласова помощ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Портфейл"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Скенер за QR кодове"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Отключване"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройството е заключено"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Извършва се сканиране на лице"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Изпращане"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Лицето не е разпознато"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Използвайте отпечатък"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е включен."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентът на батерията е неизвестен."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Самолетен режим."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Функцията за виртуална частна мрежа (VPN) е включена."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> процента батерия."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерията е на <xliff:g id="PERCENTAGE">%1$s</xliff:g> процента. Още около <xliff:g id="TIME">%2$s</xliff:g> въз основа на използването"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Батерията се зарежда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Вижте всички известия"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter бе активиран."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Вибрира при звънене."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в това приложение, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Напред"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Споделяне или записване на приложение"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Да се разреши ли на това приложение да споделя или записва?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Когато споделяте, записвате или предавате, това приложение има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Когато споделяте, записвате или предавате, това приложение има достъп до всичко, което се показва или възпроизвежда в него, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Блокирано от системния ви администратор"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Заснемането на екрана е деактивирано от правило за устройството"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Изчистване на всички"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управление"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отключване с цел използване"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки за заключения екран"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR код: сканиране"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Да се изключат ли мобилните данни?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Няма да можете да използвате данни или интернет чрез <xliff:g id="CARRIER">%s</xliff:g>. Ще имате достъп до интернет само през Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"оператора си"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Искате ли да се върнете към <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мрежата за мобилни данни няма да се превключва автоматично въз основа на наличността"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Не, благодаря"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Да, превключване"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"От Настройки не може да се получи потвърждение за отговора ви, защото заявката за разрешение се прикрива от приложение."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Искате ли да разрешите на <xliff:g id="APP_0">%1$s</xliff:g> да показва части от <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Може да чете информация от <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Установена е временна връзка"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба връзка"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Връзката за мобилни данни няма да е автоматична"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма връзка"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Няма други налични мрежи"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9533963..5c4013d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR কোড স্ক্যানার"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ফেস স্ক্যান করা হচ্ছে"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"পাঠান"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ফেস শনাক্ত করা যায়নি"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"বিমান মোড৷"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN চালু আছে।"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ব্যাটারি <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, বর্তমান ব্যবহারের উপর ভিত্তি করে আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ব্যাটারি চার্জ হচ্ছে, এখন <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ চার্জ আছে৷"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"সমস্ত বিজ্ঞপ্তি দেখুন"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"টেলি টাইপরাইটার সক্ষম করা আছে৷"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"রিং বাজার সাথে স্পন্দিত করুন৷"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"কোনও অ্যাপ আপনার শেয়ার করা, রেকর্ড করা বা কাস্ট করার সময়, সেই অ্যাপে দেখা যায় বা খেলা হয় এমন সব কিছু অ্যাক্সেস করার অনুমতি <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর আছে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"চালিয়ে যান"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"অ্যাপ শেয়ার বা রেকর্ড করা"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"এই অ্যাপকে শেয়ার বা রেকর্ড করার অনুমতি দেবেন?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"আপনি শেয়ার, রেকর্ড বা কাস্ট করার সময় স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো হয়েছে এমন সব কিছুই এই অ্যাপ অ্যাক্সেস করতে পারবে। সেই জন্য পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"কোনও অ্যাপের মাধ্যমে শেয়ার, রেকর্ড বা কাস্ট করার সময়, অ্যাপে দৃশ্যমান বা তাতে চালানো হয়েছে এমন সব কিছুই এই অ্যাপ অ্যাক্সেস করতে পারবে। সেই জন্য পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ বা অন্য সংবেদনশীল তথ্য সম্পর্কে সতর্ক থাকুন।"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"আপনার আইটি অ্যাডমিন ব্লক করেছেন"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ডিভাইস নীতির কারণে স্ক্রিন ক্যাপচার করার প্রসেস বন্ধ করা আছে"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"সবকিছু সাফ করুন"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"পরিচালনা করুন"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR কোড স্ক্যান করুন"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"মোবাইল ডেটা বন্ধ করবেন?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপনি \'<xliff:g id="CARRIER">%s</xliff:g>\'-এর মাধ্যমে ডেটা অথবা ইন্টারনেট অ্যাক্সেস করতে পারবেন না। শুধুমাত্র ওয়াই-ফাইয়ের মাধ্যমেই ইন্টারনেট অ্যাক্সেস করা যাবে।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"আপনার পরিষেবা প্রদানকারী"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"আবার <xliff:g id="CARRIER">%s</xliff:g>-এর ডেটায় পরিবর্তন করবেন?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"উপলভ্যতার উপরে ভিত্তি করে অটোমেটিক মোবাইল ডেটায় পরিবর্তন করা হবে না"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"না থাক"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"হ্যাঁ, পাল্টান"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"একটি অ্যাপ কোনও অনুমোদনের অনুরোধকে ঢেকে দিচ্ছে, তাই সেটিংস থেকে আপনার প্রতিক্রিয়া যাচাই করা যাচ্ছে না।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটিকে <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখানোর অনুমতি দেবেন?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- এটি <xliff:g id="APP">%1$s</xliff:g> এর তথ্য অ্যাক্সেস করতে পারবে"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"সাময়িকভাবে কানেক্ট করা হয়েছে"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"খারাপ কানেকশন"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"মোবাইল ডেটা নিজে থেকে কানেক্ট হবে না"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"কানেকশন নেই"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনও নেটওয়ার্ক উপলভ্য নেই"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 69b09393..6b3c895 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skener QR koda"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključaj"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Nije moguće prepoznati lice"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je povezan."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak napunjenosti baterije nije poznat"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u avionu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto. Na osnovu vaše potrošnje preostalo vam je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Punjenje baterije, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Vidite sva obavještenja"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Omogućena opcija TeleTypewriter."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvuk zvona na vibraciji."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kada aplikaciju dijelite, snimate ili emitirate, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Zato budite oprezni s lozinkama, detaljima o plaćanju, porukama i drugim osjetljivim informacijama."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Nastavi"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dijelite ili snimite aplikaciju"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Dozvoliti aplikaciji da dijeli ili snima?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kada dijelite, snimate ili emitirate, aplikacija ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Zato budite oprezni s lozinkama, detaljima o plaćanju, porukama i drugim osjetljivim informacijama."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kada dijelite, snimate ili emitirate aplikaciju, ona ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Zato budite oprezni s lozinkama, detaljima o plaćanju, porukama i drugim osjetljivim informacijama."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokirao je vaš IT administrator"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Snimanje ekrana je onemogućeno pravilima uređaja"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Očisti sve"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historija"</string>
@@ -500,7 +501,7 @@
     <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="qr_code_scanner_title" msgid="5290201053875420785">"Skenirajte QR kôd"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Čitač QR koda"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil za posao"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Isključiti prijenos podataka na mobilnoj mreži?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ni internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi-ja."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vaš operater"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vratiti na operatera <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Prijenos podataka na mobilnoj mreži se neće automatski promijeniti na osnovu dostupnosti"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, hvala"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Da, promijeni"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Može čitati informacije iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Prijenos podataka se neće automatski povezati"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani s mrežom"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Druge mreže nisu dostupne"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e992615..9892d26 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistència per veu"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escàner de codis QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloqueja"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositiu bloquejat"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"S\'està escanejant la cara"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envia"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"No es reconeix la cara"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilitza l\'empremta digital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connectat."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Es desconeix el percentatge de bateria."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode d\'avió."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> per cent de bateria."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> per cent de bateria amb aproximadament <xliff:g id="TIME">%2$s</xliff:g> de temps restant segons l\'ús que en fas"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"La bateria s\'està carregant (<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%)."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Mostra totes les notificacions"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletip activat."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Mode vibració."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quan estàs compartint, gravant o emetent, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continua"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Comparteix o grava una aplicació"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vols permetre que aquesta aplicació comparteixi o gravi contingut?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Quan estàs compartint, gravant o emetent, aquesta aplicació té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Quan estàs compartint, gravant o emetent, aquesta aplicació té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloquejat per l\'administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Les captures de pantalla estan desactivades per la política de dispositius"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Esborra-ho tot"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestiona"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
@@ -430,8 +431,8 @@
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"L\'administrador ha activat el registre de xarxa, que monitora el trànsit al teu perfil de treball, però no al personal."</string>
     <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI pot veure l\'activitat de la teva xarxa, inclosos els correus electrònics i les dades de navegació."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. El teu administrador de TI pot veure la teva activitat a la xarxa, inclosos els correus electrònics i les dades de navegació."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Les aplicacions de treball es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI i el teu proveïdor de VPN poden veure la teva activitat a la xarxa en aplicacions de treball, inclosos els correus electrònics i les dades de navegació."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. El teu administrador de TI pot veure la teva activitat de xarxa, inclosos els correus electrònics i les dades de navegació."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Les aplicacions de treball es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI i el teu proveïdor de VPN poden veure la teva activitat de xarxa en aplicacions de treball, inclosos els correus electrònics i les dades de navegació."</string>
     <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Les aplicacions personals es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu proveïdor de VPN pot veure l\'activitat de la teva xarxa, inclosos els correus electrònics i les dades de navegació."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Obre la configuració de la VPN"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloqueja per utilitzar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuració de la pantalla de bloqueig"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Escaneja un codi QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> no sentiràs la pròxima alarma"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vols desactivar les dades mòbils?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"No tindràs accés a dades ni a Internet mitjançant <xliff:g id="CARRIER">%s</xliff:g>. Internet només estarà disponible per Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"el teu operador de telefonia mòbil"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vols tornar a <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Les dades mòbils no canviaran automàticament en funció de la disponibilitat"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, gràcies"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sí, fes el canvi"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Com que hi ha una aplicació que oculta una sol·licitud de permís, no es pot verificar la teva resposta des de la configuració."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vols permetre que <xliff:g id="APP_0">%1$s</xliff:g> mostri porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Pot llegir informació de l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexió temporal"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexió feble"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Les dades mòbils no es connectaran automàticament"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sense connexió"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hi ha cap altra xarxa disponible"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 56b9185..18894d2 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasová asistence"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peněženka"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Čtečka QR kódů"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Odemknout"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Zařízení uzamčeno"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenování obličeje"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Odeslat"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Obličej nelze rozpoznat"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Použijte otisk prstu"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Rozhraní Bluetooth je připojeno."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procento baterie není známé."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim Letadlo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuto."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterie je nabitá na <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, při vašem používání vydrží ještě <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterie se nabíjí. Nabito: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Zobrazit všechna oznámení"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Rozhraní TeleTypewriter zapnuto."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibrační vyzvánění."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Když sdílíte, nahráváte nebo odesíláte aplikaci, aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> má přístup k veškerému obsahu, který je v této aplikaci zobrazen nebo přehráván. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Pokračovat"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Sdílení nebo nahrání aplikace"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Povolit této aplikaci sdílet nebo nahrávat?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Když sdílíte, nahráváte nebo odesíláte obsah, aplikace má přístup ke všemu, co je viditelné na obrazovce nebo se přehrává v zařízení. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Když sdílíte, nahráváte nebo odesíláte aplikaci, aplikace má přístup ke všemu, co je v této aplikaci zobrazeno nebo se přehrává. Dejte proto pozor na hesla, platební údaje, zprávy nebo jiné citlivé informace."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokováno administrátorem IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Záznam obrazovky je zakázán zásadami zařízení"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Smazat vše"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odemknout a použít"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Při načítání karet došlo k problému, zkuste to později"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavení obrazovky uzamčení"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Naskenovat QR kód"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vypnout mobilní data?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Prostřednictvím <xliff:g id="CARRIER">%s</xliff:g> nebudete moci používat data ani internet. Internet bude dostupný pouze přes Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vašeho operátora"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Přepnout zpět na operátora <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilní data se nebudou automaticky přepínat podle dostupnosti"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, díky"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ano, přepnout"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Žádost o oprávnění je blokována jinou aplikací. Nastavení proto vaši odpověď nemůže ověřit."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Povolit aplikaci <xliff:g id="APP_0">%1$s</xliff:g> zobrazovat ukázky z aplikace <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Může číst informace z aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasně připojeno"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Nekvalitní připojení"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilní data se nebudou připojovat automaticky"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Žádné připojení"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Žádné další sítě nejsou k dispozici"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c977058..8dbe978 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Taleassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kodescanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås op"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheden er låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanner ansigt"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansigt kan ikke genkendes"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Brug fingeraftryk i stedet"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tilsluttet."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flytilstand."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN er slået til."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteriniveauet er på <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, så du har ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batteriet oplades. <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Se alle notifikationer"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter aktiveret."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ringervibration."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Når du deler, optager eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsæt"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Del eller optag en app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vil du tillade, at denne app deler eller optager?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Når du deler, optager eller caster, har denne app adgang til alt, der vises på din skærm eller afspilles på din enhed. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Når du deler, optager eller caster en app, har denne app adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med adgangskoder, betalingsoplysninger, beskeder og andre følsomme oplysninger."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokeret af din it-administrator"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Screenshots er deaktiveret af enhedspolitikken"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Ryd alle"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås op for at bruge"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Dine kort kunne ikke hentes. Prøv igen senere."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR-kode"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vil du deaktivere mobildata?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Du vil ikke have data- eller internetadgang via <xliff:g id="CARRIER">%s</xliff:g>. Der vil kun være adgang til internettet via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"dit mobilselskab"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vil du skifte tilbage til <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobildata skifter ikke automatisk på baggrund af tilgængelighed"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nej tak"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, skift"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Indstillinger kan ikke bekræfte dit svar, da en app dækker for en anmodning om tilladelse."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vil du give <xliff:g id="APP_0">%1$s</xliff:g> tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Den kan læse oplysninger fra <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Midlertidigt forbundet"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Ingen automatisk mobildataforbindelse"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Der er ingen forbindelse"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Der er ingen andre tilgængelige netværk"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 74f9c5f..5191b47 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sprachassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-Code-Scanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Entsperren"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Gerät gesperrt"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gesicht wird gescannt"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Senden"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Gesicht nicht erkannt"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Fingerabdruck verwenden"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Mit Bluetooth verbunden"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akkustand unbekannt."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugmodus"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN an."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akku bei <xliff:g id="NUMBER">%d</xliff:g> Prozent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akku bei <xliff:g id="PERCENTAGE">%1$s</xliff:g> Prozent. Bei deinem Nutzungsmuster hast du noch Strom für etwa <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Akku wird aufgeladen, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> Prozent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Alle Benachrichtigungen ansehen"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Schreibtelefonie aktiviert"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Klingeltonmodus \"Vibration\""</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Beim Teilen, Aufnehmen oder Übertragen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Weiter"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"App teilen oder aufnehmen"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Dieser App das Teilen oder Aufnehmen erlauben?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Beim Teilen, Aufnehmen oder Übertragen hat diese App Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Beim Teilen, Aufnehmen oder Übertragen einer App hat diese App Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Vom IT-Administrator blockiert"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Bildschirmaufnahme ist durch die Geräterichtlinien deaktiviert"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Verwalten"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Verlauf"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Zum Verwenden entsperren"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Einstellungen für den Sperrbildschirm"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR-Code scannen"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Lautloser Weckruf <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobile Daten deaktivieren?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Du kannst dann nicht mehr über <xliff:g id="CARRIER">%s</xliff:g> auf Daten und das Internet zugreifen. Das Internet ist nur noch über WLAN verfügbar."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"deinen Mobilfunkanbieter"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Zurück zu <xliff:g id="CARRIER">%s</xliff:g> wechseln?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile Daten werden nicht je nach Verfügbarkeit automatisch gewechselt"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nein danke"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, wechseln"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Deine Eingabe wird von \"Einstellungen\" nicht erkannt, weil die Berechtigungsanfrage von einer App verdeckt wird."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> erlauben, Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzuzeigen?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Darf Informationen aus <xliff:g id="APP">%1$s</xliff:g> lesen"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vorübergehend verbunden"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Schwache Verbindung"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Keine automatische Verbindung über mobile Daten"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Keine Verbindung"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Keine anderen Netzwerke verfügbar"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 59f645d..448e1e0 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Φωνητική υποβοήθηση"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Πορτοφόλι"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Σάρωση κωδικών QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Ξεκλείδωμα"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Η συσκευή κλειδώθηκε"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Σάρωση προσώπου"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Αποστολή"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Αδύνατη η αναγν. προσώπου"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Χρησιμ. δακτυλ. αποτύπ."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Το Bluetooth είναι συνδεδεμένο."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Άγνωστο ποσοστό μπαταρίας."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Λειτουργία πτήσης."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ενεργό."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Μπαταρία <xliff:g id="NUMBER">%d</xliff:g> τοις εκατό."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Μπαταρία στο <xliff:g id="PERCENTAGE">%1$s</xliff:g> τοις εκατό. Περίπου <xliff:g id="TIME">%2$s</xliff:g> ακόμη, βάσει της χρήσης σας"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Φόρτιση μπαταρίας: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Δείτε όλες τις ειδοποιήσεις"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Το TeleTypewriter ενεργοποιήθηκε."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Δόνηση ειδοποίησης ήχου."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Όταν κάνετε κοινοποίηση, εγγραφή ή μετάδοση μιας εφαρμογής, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα ή άλλες ευαίσθητες πληροφορίες."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Συνέχεια"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Κοινοποίηση ή εγγραφή εφαρμογής"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Να επιτρέπεται σε αυτήν την εφαρμογή η κοινή χρήση ή εγγραφή;"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Όταν κάνετε κοινοποίηση, εγγραφή ή μετάδοση, αυτή η εφαρμογή έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα ή άλλες ευαίσθητες πληροφορίες."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Όταν κάνετε κοινοποίηση, εγγραφή ή μετάδοση μιας εφαρμογής, αυτή η εφαρμογή έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα ή άλλες ευαίσθητες πληροφορίες."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Αποκλείστηκε από τον διαχειριστή IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Η καταγραφή οθόνης έχει απενεργοποιηθεί από την πολιτική χρήσης συσκευής."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Διαγραφή όλων"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Διαχείριση"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ιστορικό"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ξεκλείδωμα για χρήση"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ρυθμίσεις κλειδώματος οθόνης"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Σάρωση κωδικού QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Σάρωση κωδικών QR"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Δεν θα ακούσετε το επόμενο ξυπνητήρι σας <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Απενεργοποίηση δεδομένων κινητής τηλεφωνίας;"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Δεν θα έχετε πρόσβαση σε δεδομένα ή στο διαδίκτυο μέσω της εταιρείας κινητής τηλεφωνίας <xliff:g id="CARRIER">%s</xliff:g>. Θα έχετε πρόσβαση στο διαδίκτυο μόνο μέσω Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"η εταιρεία κινητής τηλεφωνίας"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Επιστροφή σε <xliff:g id="CARRIER">%s</xliff:g>;"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Δεν θα γίνεται αυτόματα εναλλαγή των δεδομένων κινητής τηλεφωνίας βάσει της διαθεσιμότητας"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Όχι, ευχαριστώ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ναι, εναλλαγή"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Επειδή μια εφαρμογή αποκρύπτει ένα αίτημα άδειας, δεν είναι δυνατή η επαλήθευση της απάντησής σας από τις Ρυθμίσεις."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Να επιτρέπεται στο <xliff:g id="APP_0">%1$s</xliff:g> να εμφανίζει τμήματα της εφαρμογής <xliff:g id="APP_2">%2$s</xliff:g>;"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Μπορεί να διαβάζει πληροφορίες από την εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Προσωρινή σύνδεση"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Ασθενής σύνδεση"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Χωρίς αυτόματη σύνδεση δεδομένων κινητ. τηλεφωνίας"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Χωρίς σύνδεση"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Δεν υπάρχουν άλλα διαθέσιμα δίκτυα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 19845f4..bfa63f6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code scanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"Unlocked"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"See all notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter enabled."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ringer vibrate."</string>
@@ -495,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR code scanner"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -734,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Turn off mobile data?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"You won\'t have access to data or the Internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -924,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 615e8b6..879d88b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -21,8 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4811759950673118541">"System UI"</string>
     <string name="battery_low_title" msgid="5319680173344341779">"Turn on Battery Saver?"</string>
-    <string name="battery_low_description" msgid="3282977755476423966">"You have <xliff:g id="PERCENTAGE">%s</xliff:g> battery left. Battery Saver turns on Dark theme, restricts background activity and delays notifications."</string>
-    <string name="battery_low_intro" msgid="5148725009653088790">"Battery Saver turns on Dark theme, restricts background activity and delays notifications."</string>
+    <string name="battery_low_description" msgid="3282977755476423966">"You have <xliff:g id="PERCENTAGE">%s</xliff:g> battery left. Battery Saver turns on Dark theme, restricts background activity, and delays notifications."</string>
+    <string name="battery_low_intro" msgid="5148725009653088790">"Battery Saver turns on Dark theme, restricts background activity, and delays notifications."</string>
     <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"Can\'t charge via USB"</string>
     <string name="invalid_charger_text" msgid="2339310107232691577">"Use the charger that came with your device"</string>
@@ -30,7 +30,7 @@
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"About Battery Saver"</string>
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Turn on"</string>
     <string name="battery_saver_start_action" msgid="8353766979886287140">"Turn on"</string>
-    <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, thanks"</string>
+    <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No thanks"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string>
     <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
     <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
@@ -64,7 +64,7 @@
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Wireless debugging not allowed"</string>
     <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"The user currently signed in to this device can’t turn on wireless debugging. To use this feature, switch to the primary user."</string>
     <string name="usb_contaminant_title" msgid="894052515034594113">"USB port disabled"</string>
-    <string name="usb_contaminant_message" msgid="7730476585174719805">"To protect your device from liquid or debris, the USB port is disabled and won’t detect any accessories.\n\nYou’ll be notified when it’s OK to use the USB port again."</string>
+    <string name="usb_contaminant_message" msgid="7730476585174719805">"To protect your device from liquid or debris, the USB port is disabled and won’t detect any accessories.\n\nYou’ll be notified when it’s okay to use the USB port again."</string>
     <string name="usb_port_enabled" msgid="531823867664717018">"USB port enabled to detect chargers and accessories"</string>
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Enable USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
@@ -85,23 +85,23 @@
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capture more"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dismiss screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshot preview"</string>
-    <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
+    <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+    <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+    <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+    <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
-    <string name="screenrecord_start_label" msgid="1750350278888217473">"Start recording?"</string>
-    <string name="screenrecord_description" msgid="1123231719680353736">"While recording, the Android System can capture any sensitive information that’s visible on your screen or played on your device. This includes passwords, payment info, photos, messages and audio."</string>
+    <string name="screenrecord_start_label" msgid="1750350278888217473">"Start Recording?"</string>
+    <string name="screenrecord_description" msgid="1123231719680353736">"While recording, Android System can capture any sensitive information that’s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio."</string>
     <string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Record entire screen"</string>
     <string name="screenrecord_option_single_app" msgid="5954863081500035825">"Record a single app"</string>
-    <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"While you\'re recording, Android has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages or other sensitive information."</string>
-    <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"While you\'re recording an app, Android has access to anything shown or played on that app. So, be careful with passwords, payment details, messages or other sensitive information."</string>
+    <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"While you\'re recording, Android has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information."</string>
+    <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"While you\'re recording an app, Android has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information."</string>
     <string name="screenrecord_start_recording" msgid="348286842544768740">"Start recording"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string>
-    <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls and ringtones"</string>
+    <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls, and ringtones"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"Microphone"</string>
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Device audio and microphone"</string>
     <string name="screenrecord_start" msgid="330991441575775004">"Start"</string>
@@ -124,8 +124,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
-    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code scanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR Code Scanner"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"Unlocked"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -140,8 +140,8 @@
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
-    <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
-    <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
+    <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string>
+    <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string>
     <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string>
     <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string>
     <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string>
@@ -163,12 +163,12 @@
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
-    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
+    <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognize face. Use fingerprint instead."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
-    <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
+    <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognize face"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
@@ -179,9 +179,14 @@
     <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Airplane mode."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
-    <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> percent."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"See all notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter enabled."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ringer vibrate."</string>
@@ -196,7 +201,7 @@
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"total silence"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"alarms only"</string>
     <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"Do Not Disturb."</string>
-    <string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"Bluetooth"</string>
+    <string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"Bluetooth."</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"Bluetooth on."</string>
     <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"Alarm set for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"More time."</string>
@@ -205,12 +210,12 @@
     <string name="accessibility_brightness" msgid="5391187016177823721">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"Mobile data is paused"</string>
     <string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Data is paused"</string>
-    <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"The data limit that you set has been reached. You are no longer using mobile data.\n\nIf you resume, charges may apply for data usage."</string>
+    <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"The data limit you set has been reached. You are no longer using mobile data.\n\nIf you resume, charges may apply for data usage."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Resume"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Location requests active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors off active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Clear all notifications."</string>
-    <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# more notification inside.}other{# more notifications inside.}}"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Screen is locked in landscape orientation."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Screen is locked in portrait orientation."</string>
@@ -229,7 +234,7 @@
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Auto-rotate"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Auto-rotate screen"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
-    <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Screensaver"</string>
+    <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Screen saver"</string>
     <string name="quick_settings_camera_label" msgid="5612076679385269339">"Camera access"</string>
     <string name="quick_settings_mic_label" msgid="8392773746295266375">"Mic access"</string>
     <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Available"</string>
@@ -248,8 +253,8 @@
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"No devices available"</string>
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi‑Fi not connected"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
-    <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Colour inversion"</string>
-    <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Colour correction"</string>
+    <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Color inversion"</string>
+    <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Color correction"</string>
     <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Manage users"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Done"</string>
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Close"</string>
@@ -307,11 +312,11 @@
     <string name="sensor_privacy_mic_camera_unblocked_toast_content" msgid="7339355093282661115">"Microphone and camera available"</string>
     <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
-    <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string>
-    <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string>
-    <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customise"</string>
+    <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games."</string>
+    <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos, and games."</string>
+    <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customize"</string>
     <string name="zen_silence_introduction_voice" msgid="853573681302712348">"This blocks ALL sounds and vibrations, including from alarms, music, videos, and games. You\'ll still be able to make phone calls."</string>
-    <string name="zen_silence_introduction" msgid="6117517737057344014">"This blocks ALL sounds and vibrations, including from alarms, music, videos and games."</string>
+    <string name="zen_silence_introduction" msgid="6117517737057344014">"This blocks ALL sounds and vibrations, including from alarms, music, videos, and games."</string>
     <string name="notification_tap_again" msgid="4477318164947497249">"Tap again to open"</string>
     <string name="tap_again" msgid="1315420114387908655">"Tap again"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string>
@@ -319,10 +324,10 @@
     <string name="keyguard_face_successful_unlock_swipe" msgid="6180997591385846073">"Unlocked by face. Swipe up to open."</string>
     <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string>
-    <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string>
-    <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
+    <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognized. Press to open."</string>
+    <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognized. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
-    <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
+    <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognized"</string>
   <string-array name="udfps_accessibility_touch_hints">
     <item msgid="1901953991150295169">"Move left"</item>
     <item msgid="5558598599408514296">"Move down"</item>
@@ -354,7 +359,7 @@
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome back, guest!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string>
-    <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string>
+    <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start over"</string>
     <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string>
     <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string>
     <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string>
@@ -364,20 +369,20 @@
     <string name="user_remove_user_title" msgid="9124124694835811874">"Remove user?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"All apps and data of this user will be deleted."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Remove"</string>
-    <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
-    <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
+    <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string>
+    <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string>
     <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Start recording or casting?"</string>
     <string name="media_projection_dialog_title" msgid="3316063622495360646">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
     <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Allow <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> to share or record?"</string>
     <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Entire screen"</string>
     <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"A single app"</string>
-    <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"When you\'re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages or other sensitive information."</string>
-    <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"When you\'re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So, be careful with passwords, payment details, messages or other sensitive information."</string>
+    <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"When you\'re sharing, recording, or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information."</string>
+    <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"When you\'re sharing, recording, or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continue"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Share or record an app"</string>
     <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Allow this app to share or record?"</string>
-    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"When you\'re sharing, recording or casting, this app has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages or other sensitive information."</string>
-    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"When you\'re sharing, recording or casting an app, this app has access to anything shown or played on that app. So be careful with passwords, payment details, messages or other sensitive information."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"When you\'re sharing, recording, or casting, this app has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"When you\'re sharing, recording, or casting an app, this app has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information."</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blocked by your IT admin"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Screen capturing is disabled by device policy"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Clear all"</string>
@@ -396,19 +401,19 @@
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string>
     <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"This device is provided by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"This device belongs to your organization and is connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
-    <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the Internet through <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+    <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the internet through <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
     <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"This device belongs to your organization"</string>
     <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
     <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"This device belongs to your organization and is connected to the internet through VPNs"</string>
-    <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the Internet through VPNs"</string>
+    <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the internet through VPNs"</string>
     <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Your organization may monitor network traffic in your work profile"</string>
     <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> may monitor network traffic in your work profile"</string>
     <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Work profile network activity is visible to your IT admin"</string>
     <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Network may be monitored"</string>
-    <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"This device is connected to the Internet through VPNs"</string>
-    <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Your work apps are connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
-    <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Your personal apps are connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
-    <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"This device is connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"This device is connected to the internet through VPNs"</string>
+    <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Your work apps are connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Your personal apps are connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+    <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"This device is connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="monitoring_title_financed_device" msgid="3659962357973919387">"This device is provided by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="monitoring_title_device_owned" msgid="7029691083837606324">"Device management"</string>
     <string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
@@ -417,22 +422,22 @@
     <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
     <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
     <string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
-    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps and change this device\'s settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
+    <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps, and change this devices settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
     <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organization.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organization installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organization installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string>
-    <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"This device is connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"This device is connected to the Internet through <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Your work apps are connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity in work apps, including emails and browsing data, is visible to your IT admin and VPN provider."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Your personal apps are connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your VPN provider."</string>
+    <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"This device is connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"This device is connected to the internet through <xliff:g id="VPN_APP_0">%1$s</xliff:g> and <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Your work apps are connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity in work apps, including emails and browsing data, is visible to your IT admin and VPN provider."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Your personal apps are connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your VPN provider."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Open VPN settings"</string>
-    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
+    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps you use, your location, and your screen time."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
-    <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by trust agent"</string>
+    <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Kept unlocked by TrustAgent"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Sound settings"</string>
     <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatically caption media"</string>
@@ -440,21 +445,21 @@
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string>
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string>
-    <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string>
+    <string name="sound_settings" msgid="8874581353127418308">"Sound &amp; vibration"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin."</string>
-    <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up and hold to unpin."</string>
+    <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"This keeps it in view until you unpin. Swipe up &amp; hold to unpin."</string>
     <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"This keeps it in view until you unpin. Touch &amp; hold Overview to unpin."</string>
     <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"This keeps it in view until you unpin. Touch &amp; hold Home to unpin."</string>
-    <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible, such as contacts and email content."</string>
+    <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Personal data may be accessible (such as contacts and email content)."</string>
     <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Pinned app may open other apps."</string>
-    <string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch and hold Back and Overview buttons"</string>
-    <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch and hold Back and Home buttons"</string>
-    <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"To unpin this app, swipe up and hold"</string>
+    <string name="screen_pinning_toast" msgid="8177286912533744328">"To unpin this app, touch &amp; hold Back and Overview buttons"</string>
+    <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"To unpin this app, touch &amp; hold Back and Home buttons"</string>
+    <string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"To unpin this app, swipe up &amp; hold"</string>
     <string name="screen_pinning_positive" msgid="3285785989665266984">"Got it"</string>
-    <string name="screen_pinning_negative" msgid="6882816864569211666">"No, thanks"</string>
+    <string name="screen_pinning_negative" msgid="6882816864569211666">"No thanks"</string>
     <string name="screen_pinning_start" msgid="7483998671383371313">"App pinned"</string>
     <string name="screen_pinning_exit" msgid="4553787518387346893">"App unpinned"</string>
     <string name="stream_voice_call" msgid="7468348170702375660">"Call"</string>
@@ -464,7 +469,7 @@
     <string name="stream_alarm" msgid="16058075093011694">"Alarm"</string>
     <string name="stream_notification" msgid="7930294049046243939">"Notification"</string>
     <string name="stream_bluetooth_sco" msgid="6234562365528664331">"Bluetooth"</string>
-    <string name="stream_dtmf" msgid="7322536356554673067">"Dual multi-tone frequency"</string>
+    <string name="stream_dtmf" msgid="7322536356554673067">"Dual multi tone frequency"</string>
     <string name="stream_accessibility" msgid="3873610336741987152">"Accessibility"</string>
     <string name="volume_ringer_status_normal" msgid="1339039682222461143">"Ring"</string>
     <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Vibrate"</string>
@@ -493,9 +498,9 @@
     <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Tap to open"</string>
     <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Updating"</string>
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
-    <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
+    <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards, please try again later"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR code scanner"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -504,17 +509,17 @@
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Hotspot"</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 customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
-    <string name="tuner_persistent_warning" msgid="230466285569307806">"These experimental features may change, break or disappear in future releases. Proceed with caution."</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>
+    <string name="tuner_persistent_warning" msgid="230466285569307806">"These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
     <string name="got_it" msgid="477119182261892069">"Got it"</string>
     <string name="tuner_toast" msgid="3812684836514766951">"Congrats! System UI Tuner has been added to Settings"</string>
-    <string name="remove_from_settings" msgid="633775561782209994">"Remove from settings"</string>
+    <string name="remove_from_settings" msgid="633775561782209994">"Remove from Settings"</string>
     <string name="remove_from_settings_prompt" msgid="551565437265615426">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string>
     <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string>
-    <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string>
+    <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Face-based"</string>
     <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
     <string name="inline_done_button" msgid="6043094985588909584">"Done"</string>
     <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string>
@@ -527,10 +532,10 @@
     <string name="notification_channel_summary_default" msgid="3282930979307248890">"May ring or vibrate based on phone settings"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
-    <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Status:&lt;/b&gt; promoted to default"</string>
-    <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"&lt;b&gt;Status:&lt;/b&gt; demoted to silent"</string>
-    <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"&lt;b&gt;Status:&lt;/b&gt; ranked higher"</string>
-    <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;Status:&lt;/b&gt; ranked lower"</string>
+    <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Status:&lt;/b&gt; Promoted to Default"</string>
+    <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"&lt;b&gt;Status:&lt;/b&gt; Demoted to Silent"</string>
+    <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"&lt;b&gt;Status:&lt;/b&gt; Ranked Higher"</string>
+    <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"&lt;b&gt;Status:&lt;/b&gt; Ranked Lower"</string>
     <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"Shows at the top of conversation notifications and as a profile picture on lock screen"</string>
     <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble"</string>
     <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"Shows at the top of conversation notifications and as a profile picture on lock screen, interrupts Do Not Disturb"</string>
@@ -543,15 +548,15 @@
     <string name="notification_delegate_header" msgid="1264510071031479920">"Proxied notification"</string>
     <string name="notification_channel_dialog_title" msgid="6856514143093200019">"All <xliff:g id="APP_NAME">%1$s</xliff:g> notifications"</string>
     <string name="see_more_title" msgid="7409317011708185729">"See more"</string>
-    <string name="feedback_alerted" msgid="5192459808484271208">"This notification was automatically &lt;b&gt;promoted to default&lt;/b&gt; by the system."</string>
-    <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to silent&lt;/b&gt; by the system."</string>
+    <string name="feedback_alerted" msgid="5192459808484271208">"This notification was automatically &lt;b&gt;promoted to Default&lt;/b&gt; by the system."</string>
+    <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically &lt;b&gt;demoted to Silent&lt;/b&gt; by the system."</string>
     <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically &lt;b&gt;ranked higher&lt;/b&gt; in your shade."</string>
     <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically &lt;b&gt;ranked lower&lt;/b&gt; in your shade."</string>
     <string name="feedback_prompt" msgid="3656728972307896379">"Let the developer know your feedback. Was this correct?"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6111817750774381094">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="1561909368876911701">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> closed"</string>
     <string name="notification_more_settings" msgid="4936228656989201793">"More settings"</string>
-    <string name="notification_app_settings" msgid="8963648463858039377">"Customise"</string>
+    <string name="notification_app_settings" msgid="8963648463858039377">"Customize"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"Show bubble"</string>
     <string name="notification_conversation_unbubble" msgid="6908427185031099868">"Remove bubbles"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -570,7 +575,7 @@
     <string name="keyboard_key_dpad_down" msgid="2110172278574325796">"Down"</string>
     <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Left"</string>
     <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Right"</string>
-    <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centre"</string>
+    <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
@@ -580,7 +585,7 @@
     <string name="keyboard_key_media_next" msgid="8502476691227914952">"Next"</string>
     <string name="keyboard_key_media_previous" msgid="5637875709190955351">"Previous"</string>
     <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Rewind"</string>
-    <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Fast-Forward"</string>
+    <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Fast Forward"</string>
     <string name="keyboard_key_page_up" msgid="173914303254199845">"Page Up"</string>
     <string name="keyboard_key_page_down" msgid="9035902490071829731">"Page Down"</string>
     <string name="keyboard_key_forward_del" msgid="5325501825762733459">"Delete"</string>
@@ -592,10 +597,10 @@
     <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"Remove attachment"</string>
     <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"System"</string>
     <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Home"</string>
-    <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Recent"</string>
+    <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Recents"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Back"</string>
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
-    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard Shortcuts"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
@@ -637,7 +642,7 @@
     <string name="save" msgid="3392754183673848006">"Save"</string>
     <string name="reset" msgid="8715144064608810383">"Reset"</string>
     <string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
-    <string name="accessibility_key" msgid="3471162841552818281">"Customised navigation button"</string>
+    <string name="accessibility_key" msgid="3471162841552818281">"Custom navigation button"</string>
     <string name="left_keycode" msgid="8211040899126637342">"Left keycode"</string>
     <string name="right_keycode" msgid="2480715509844798438">"Right keycode"</string>
     <string name="left_icon" msgid="5036278531966897006">"Left icon"</string>
@@ -649,7 +654,7 @@
     <string name="qs_edit" msgid="5583565172803472437">"Edit"</string>
     <string name="tuner_time" msgid="2450785840990529997">"Time"</string>
   <string-array name="clock_options">
-    <item msgid="3986445361435142273">"Show hours, minutes and seconds"</item>
+    <item msgid="3986445361435142273">"Show hours, minutes, and seconds"</item>
     <item msgid="1271006222031257266">"Show hours and minutes (default)"</item>
     <item msgid="6135970080453877218">"Don\'t show this icon"</item>
   </string-array>
@@ -676,7 +681,7 @@
     <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"Signed in as <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"choose user"</string>
-    <string name="data_connection_no_internet" msgid="691058178914184544">"No Internet"</string>
+    <string name="data_connection_no_internet" msgid="691058178914184544">"No internet"</string>
     <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
@@ -684,14 +689,14 @@
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
     <string name="thermal_shutdown_title" msgid="2702966892682930264">"Phone turned off due to heat"</string>
     <string name="thermal_shutdown_message" msgid="6142269839066172984">"Your phone is now running normally.\nTap for more info"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n	• Use resource-intensive apps (such as gaming, video or navigation apps)\n	• Download or upload large files\n	• Use your phone in high temperatures"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n	• Use resource-intensive apps (such as gaming, video, or navigation apps)\n	• Download or upload large files\n	• Use your phone in high temperatures"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"See care steps"</string>
     <string name="high_temp_title" msgid="2218333576838496100">"Phone is getting warm"</string>
-    <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features are limited while phone cools down.\nTap for more info"</string>
-    <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string>
+    <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features limited while phone cools down.\nTap for more info"</string>
+    <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally."</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string>
     <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string>
-    <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it and take care as the cable may also be warm."</string>
+    <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it, and take care as the cable may also be warm."</string>
     <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string>
     <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string>
     <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string>
@@ -717,11 +722,11 @@
     <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string>
     <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
     <string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string>
-    <string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to find out more."</string>
+    <string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to learn more."</string>
     <string name="app_info" msgid="5153758994129963243">"App info"</string>
     <string name="go_to_web" msgid="636673528981366511">"Go to browser"</string>
     <string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth is off"</string>
@@ -732,18 +737,22 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"Apps running in background"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Tap for details on battery and data usage"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Turn off mobile data?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"You won\'t have access to data or the Internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"You wont have access to data or the internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your carrier"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data wont automatically switch based on availability"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
-    <string name="slice_permission_text_1" msgid="6675965177075443714">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="slice_permission_text_2" msgid="6758906940360746983">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="slice_permission_text_1" msgid="6675965177075443714">"- It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="slice_permission_text_2" msgid="6758906940360746983">"- It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
     <string name="slice_permission_allow" msgid="6340449521277951123">"Allow"</string>
     <string name="slice_permission_deny" msgid="6870256451658176895">"Deny"</string>
     <string name="auto_saver_title" msgid="6873691178754086596">"Tap to schedule Battery Saver"</string>
     <string name="auto_saver_text" msgid="3214960308353838764">"Turn on when battery is likely to run out"</string>
-    <string name="no_auto_saver_action" msgid="7467924389609773835">"No, thanks"</string>
+    <string name="no_auto_saver_action" msgid="7467924389609773835">"No thanks"</string>
     <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
     <string name="ongoing_privacy_dialog_a11y_title" msgid="2205794093673327974">"In use"</string>
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
@@ -762,8 +771,8 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
-    <string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
-    <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
+    <string name="magnification_window_title" msgid="4863914360847258333">"Magnification Window"</string>
+    <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification Window Controls"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
     <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
     <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
@@ -774,7 +783,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
-    <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
+    <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customize or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
     <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string>
     <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string>
     <string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Move top right"</string>
@@ -787,15 +796,15 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Choose app to add controls"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
-    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
-    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
-    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favourite"</string>
-    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavourite"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favorited"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavorited"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favorite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavorite"</string>
     <string name="accessibility_control_move" msgid="8980344493796647792">"Move to position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Choose controls to access from Quick Settings"</string>
-    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
+    <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold &amp; drag to rearrange controls"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"All controls removed"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Changes not saved"</string>
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"See other apps"</string>
@@ -806,11 +815,11 @@
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
-    <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
-    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
-    <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
+    <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from lock screen?"</string>
+    <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes any time in Settings."</string>
+    <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from lock screen?"</string>
     <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
-    <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
+    <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No thanks"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Verify <xliff:g id="DEVICE">%s</xliff:g>"</string>
@@ -845,7 +854,7 @@
     <string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
     <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
-    <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure that the control is still available and that the app settings haven’t changed."</string>
+    <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure the control is still available and that the app settings haven’t changed."</string>
     <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
@@ -853,7 +862,7 @@
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
-    <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
+    <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device selected"</string>
     <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
     <string name="media_output_dialog_disconnected" msgid="7090512852817111185">"(disconnected)"</string>
     <string name="media_output_dialog_connect_failed" msgid="3080972621975339387">"Can\'t switch. Tap to try again."</string>
@@ -865,9 +874,9 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
-    <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
+    <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting"</string>
     <string name="media_output_broadcasting_message" msgid="4150299923404886073">"To listen to your broadcast, people nearby with compatible Bluetooth devices can scan your QR code or use your broadcast name and password"</string>
-    <string name="media_output_broadcast_name" msgid="8786127091542624618">"Broadcast name"</string>
+    <string name="media_output_broadcast_name" msgid="8786127091542624618">"Broadcast Name"</string>
     <string name="media_output_broadcast_code" msgid="870795639644728542">"Password"</string>
     <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Save"</string>
     <string name="media_output_broadcast_starting" msgid="8130153654166235557">"Starting…"</string>
@@ -878,21 +887,21 @@
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
     <string name="select_conversation_title" msgid="6716364118095089519">"Conversation widgets"</string>
-    <string name="select_conversation_text" msgid="3376048251434956013">"Tap a conversation to add it to your home screen"</string>
+    <string name="select_conversation_text" msgid="3376048251434956013">"Tap a conversation to add it to your Home screen"</string>
     <string name="no_conversations_text" msgid="5354115541282395015">"Your recent conversations will show up here"</string>
     <string name="priority_conversations" msgid="3967482288896653039">"Priority conversations"</string>
     <string name="recent_conversations" msgid="8531874684782574622">"Recent conversations"</string>
     <string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> days ago"</string>
     <string name="one_week_timestamp" msgid="4925600765473875590">"1 week ago"</string>
     <string name="two_weeks_timestamp" msgid="9111801081871962155">"2 weeks ago"</string>
-    <string name="over_one_week_timestamp" msgid="3770560704420807142">"More than 1 week ago"</string>
-    <string name="over_two_weeks_timestamp" msgid="6300507859007874050">"More than 2 weeks ago"</string>
+    <string name="over_one_week_timestamp" msgid="3770560704420807142">"Over 1 week ago"</string>
+    <string name="over_two_weeks_timestamp" msgid="6300507859007874050">"Over 2 weeks ago"</string>
     <string name="birthday_status" msgid="2596961629465396761">"Birthday"</string>
-    <string name="birthday_status_content_description" msgid="682836371128282925">"It\'s <xliff:g id="NAME">%1$s</xliff:g>\'s birthday"</string>
+    <string name="birthday_status_content_description" msgid="682836371128282925">"It\'s <xliff:g id="NAME">%1$s</xliff:g>s birthday"</string>
     <string name="upcoming_birthday_status" msgid="2005452239256870351">"Birthday soon"</string>
-    <string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"It\'s <xliff:g id="NAME">%1$s</xliff:g>\'s birthday soon"</string>
+    <string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"It\'s <xliff:g id="NAME">%1$s</xliff:g>s birthday soon"</string>
     <string name="anniversary_status" msgid="1790034157507590838">"Anniversary"</string>
-    <string name="anniversary_status_content_description" msgid="8212171790843327442">"It\'s <xliff:g id="NAME">%1$s</xliff:g>\'s anniversary"</string>
+    <string name="anniversary_status_content_description" msgid="8212171790843327442">"It\'s <xliff:g id="NAME">%1$s</xliff:g>s anniversary"</string>
     <string name="location_status" msgid="1294990572202541812">"Sharing location"</string>
     <string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> is sharing location"</string>
     <string name="new_story_status" msgid="9012195158584846525">"New story"</string>
@@ -905,7 +914,7 @@
     <string name="status_before_loading" msgid="1500477307859631381">"Content will show up soon"</string>
     <string name="missed_call" msgid="4228016077700161689">"Missed call"</string>
     <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
-    <string name="people_tile_description" msgid="8154966188085545556">"See recent messages, missed calls and status updates"</string>
+    <string name="people_tile_description" msgid="8154966188085545556">"See recent messages, missed calls, and status updates"</string>
     <string name="people_tile_title" msgid="6589377493334871272">"Conversation"</string>
     <string name="paused_by_dnd" msgid="7856941866433556428">"Paused by Do Not Disturb"</string>
     <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> sent a message: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -916,14 +925,16 @@
     <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tap for more information"</string>
     <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"No alarm set"</string>
     <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"Fingerprint sensor"</string>
-    <string name="accessibility_authenticate_hint" msgid="798914151813205721">"Authenticate"</string>
+    <string name="accessibility_authenticate_hint" msgid="798914151813205721">"authenticate"</string>
     <string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string>
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
-    <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
+    <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
@@ -935,7 +946,7 @@
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string>
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
-    <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string>
+    <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect ethernet"</string>
     <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string>
     <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Turn off Airplane mode"</string>
     <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
@@ -959,13 +970,13 @@
     <string name="clipboard_text_copied" msgid="5100836834278976679">"Text copied"</string>
     <string name="clipboard_image_copied" msgid="3793365360174328722">"Image copied"</string>
     <string name="clipboard_content_copied" msgid="144452398567828145">"Content copied"</string>
-    <string name="clipboard_editor" msgid="2971197550401892843">"Clipboard editor"</string>
+    <string name="clipboard_editor" msgid="2971197550401892843">"Clipboard Editor"</string>
     <string name="clipboard_overlay_window_name" msgid="6450043652167357664">"Clipboard"</string>
     <string name="clipboard_image_preview" msgid="2156475174343538128">"Image preview"</string>
     <string name="clipboard_edit" msgid="4500155216174011640">"edit"</string>
     <string name="add" msgid="81036585205287996">"Add"</string>
     <string name="manage_users" msgid="1823875311934643849">"Manage users"</string>
-    <string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Split screen."</string>
+    <string name="drag_split_not_supported" msgid="4326847447699729722">"This notification does not support dragging to Splitscreen."</string>
     <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string>
     <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string>
     <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index 09401c3..4dbabcf 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -23,11 +23,11 @@
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
-    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+    <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No Notifications"</string>
     <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
     <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
-    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+    <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and Microphone are recording"</string>
     <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
     <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
-    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
+    <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and Microphone stopped recording"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 19845f4..bfa63f6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code scanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"Unlocked"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"See all notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter enabled."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ringer vibrate."</string>
@@ -495,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR code scanner"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -734,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Turn off mobile data?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"You won\'t have access to data or the Internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -924,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 19845f4..bfa63f6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code scanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"Unlocked"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Can’t recognise face"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"See all notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter enabled."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ringer vibrate."</string>
@@ -495,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scan QR code"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR code scanner"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -734,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Turn off mobile data?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"You won\'t have access to data or the Internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Switch back to <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobile data won\'t automatically switch based on availability"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No thanks"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yes, switch"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -924,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Poor connection"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index b028bf3..5f0be61 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎Voice Assist‎‏‎‎‏‎"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎Wallet‎‏‎‎‏‎"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎QR Code Scanner‎‏‎‎‏‎"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎Unlock‎‏‎‎‏‎"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎Unlocked‎‏‎‎‏‎"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎Device locked‎‏‎‎‏‎"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎Scanning face‎‏‎‎‏‎"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎Send‎‏‎‎‏‎"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎Can’t recognize face‎‏‎‎‏‎"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎Use fingerprint instead‎‏‎‎‏‎"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎Bluetooth connected.‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎Battery percentage unknown.‎‏‎‎‏‎"</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎Airplane mode.‎‏‎‎‏‎"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎VPN on.‎‏‎‎‏‎"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ percent.‎‏‎‎‏‎"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ percent, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎Battery charging, ‎‏‎‎‏‏‎<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>‎‏‎‎‏‏‏‎ percent.‎‏‎‎‏‎"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎See all notifications‎‏‎‎‏‎"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎TeleTypewriter enabled.‎‏‎‎‏‎"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎Ringer vibrate.‎‏‎‎‏‎"</string>
@@ -495,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎Unlock to use‎‏‎‎‏‎"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎There was a problem getting your cards, please try again later‎‏‎‎‏‎"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎Lock screen settings‎‏‎‎‏‎"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎Scan QR code‎‏‎‎‏‎"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎QR code scanner‎‏‎‎‏‎"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎Work profile‎‏‎‎‏‎"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎Airplane mode‎‏‎‎‏‎"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎You won\'t hear your next alarm ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -734,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎Turn off mobile data?‎‏‎‎‏‎"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎You wont have access to data or the internet through ‎‏‎‎‏‏‎<xliff:g id="CARRIER">%s</xliff:g>‎‏‎‎‏‏‏‎. Internet will only be available via Wi-Fi.‎‏‎‎‏‎"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎your carrier‎‏‎‎‏‎"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎Switch back to ‎‏‎‎‏‏‎<xliff:g id="CARRIER">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‎Mobile data wont automatically switch based on availability‎‏‎‎‏‎"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎No thanks‎‏‎‎‏‎"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎Yes, switch‎‏‎‎‏‎"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎Because an app is obscuring a permission request, Settings can’t verify your response.‎‏‎‎‏‎"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APP_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to show ‎‏‎‎‏‏‎<xliff:g id="APP_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎ slices?‎‏‎‎‏‎"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎- It can read information from ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -924,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎Mobile data‎‏‎‎‏‎"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="STATE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ / ‎‏‎‎‏‏‎<xliff:g id="NETWORKMODE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎Connected‎‏‎‎‏‎"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎Temporarily connected‎‏‎‎‏‎"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎Poor connection‎‏‎‎‏‎"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎Mobile data won\'t auto‑connect‎‏‎‎‏‎"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎No connection‎‏‎‎‏‎"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎No other networks available‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6967379..639e50d 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Billetera"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de código QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando rostro"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"No se reconoce el rostro"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella dactilar"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Se desconoce el porcentaje de la batería."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo de avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batería <xliff:g id="NUMBER">%d</xliff:g> por ciento"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento; tiempo restante: aproximadamente <xliff:g id="TIME">%2$s</xliff:g> en función del uso"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batería cargando: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas las notificaciones"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletipo habilitado"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Timbre en vibración"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cuando compartas, grabes o transmitas una app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo el contenido que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes y otra información sensible."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir o grabar una app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"¿Quieres permitir que esta app comparta o grabe tu pantalla?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Cuando compartas, grabes o transmitas contenido, esta app podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes y otra información sensible que pueda estar visible."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Cuando compartas, grabes o transmitas una app, esta app podrá acceder a todo el contenido que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes y otra información sensible que pueda estar visible."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloqueada por tu administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"La captura de pantalla está inhabilitada debido a la política del dispositivo"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de pantalla de bloqueo"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Escanear QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"¿Deseas desactivar los datos móviles?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"No tendrás acceso a datos móviles ni a Internet a través de <xliff:g id="CARRIER">%s</xliff:g>. Solo podrás conectarte a Internet mediante Wi‑Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"tu proveedor"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"¿Volver a cambiar a <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Los datos móviles no cambiarán automáticamente en función de la disponibilidad"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, gracias"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sí, cambiar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Como una app está bloqueando una solicitud de permiso, Configuración no puede verificar tu respuesta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"¿Permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Puede leer información sobre <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"No se conectarán automáticamente los datos móviles"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index cbce6bf..9acbe6f 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de códigos QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando cara"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"No se reconoce la cara"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella digital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentaje de batería desconocido."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo Avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"La red VPN está activada."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> por ciento de batería"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento de batería (<xliff:g id="TIME">%2$s</xliff:g> aproximadamente según tu uso)"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batería cargándose (<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%)."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas las notificaciones"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletipo habilitado"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Modo vibración"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cuando compartas, grabes o envíes una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo lo que muestre o reproduzca la aplicación. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir o grabar una aplicación"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"¿Permitir que esta aplicación que comparta o grabe contenido?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Cuando compartas, grabes o envíes contenido, esta aplicación podrá acceder a todo lo que se vea en tu pantalla o reproduzcas en tu dispositivo. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Cuando compartas, grabes o envíes contenido, esta aplicación podrá acceder a todo lo que se muestre o reproduzca en ella. Debes tener cuidado con contraseñas, detalles de pagos, mensajes o cualquier otra información sensible."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloqueadas por tu administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Las capturas de pantalla están inhabilitadas debido a la política de dispositivos"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Escanear código QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo Avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"¿Desactivar datos móviles?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"No tendrás acceso a datos móviles ni a Internet a través de <xliff:g id="CARRIER">%s</xliff:g>. Solo podrás conectarte a Internet mediante Wi‑Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"tu operador"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"¿Cambiar de nuevo a <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Los datos móviles no cambiarán automáticamente en función de la disponibilidad"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, gracias"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sí, cambiar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Una aplicación impide ver una solicitud de permiso, por lo que Ajustes no puede verificar tu respuesta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"¿Permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Puede leer información de <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 44812de..55ace2f 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-koodi skanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Näo skannimine"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Saada"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Nägu ei õnnestu tuvastada"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kasutage sõrmejälge"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth on ühendatud."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Aku laetuse protsent on teadmata."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lennukirežiim."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on sees."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Aku: <xliff:g id="NUMBER">%d</xliff:g> protsenti."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Aku protsent <xliff:g id="PERCENTAGE">%1$s</xliff:g>, teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Akut laetakse (<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%)."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Kõikide märguannete kuvamine"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter lubatud."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibreeriv kõlisti."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kui jagate, salvestate või kannate rakendust üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Jätka"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Rakenduse jagamine või salvestamine"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Kas lubada sellel rakendusel jagada või salvestada?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kui jagate, salvestate või kannate üle, on selle rakendusel juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kui jagate, salvestate või kannate rakendust üle, on sellel rakendusel juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite ja muu tundliku teabega ettevaatlik."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokeeris teie IT-administraator"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ekraanikuva jäädvustamine on seadmereeglitega keelatud"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tühjenda kõik"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Haldamine"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ajalugu"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avage kasutamiseks"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukustuskuva seaded"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR-koodi skannimine"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Kas lülitada mobiilne andmeside välja?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Pärast seda pole teil operaatori <xliff:g id="CARRIER">%s</xliff:g> kaudu juurdepääsu andmesidele ega internetile. Internet on saadaval ainult WiFi kaudu."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"teie operaator"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Kas vahetada tagasi operaatorile <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiilandmeside operaatorit ei vahetata saadavuse alusel automaatselt"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Tänan, ei"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Jah, vaheta"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Seaded ei saa teie vastust kinnitada, sest rakendus varjab loataotlust."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Kas lubada rakendusel <xliff:g id="APP_0">%1$s</xliff:g> näidata rakenduse <xliff:g id="APP_2">%2$s</xliff:g> lõike?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- See saab lugeda teavet rakendusest <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ajutiselt ühendatud"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Kehv ühendus"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilset andmesideühendust ei looda automaatselt"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ühendus puudub"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ühtegi muud võrku pole saadaval"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 45b4cd6..89f1ebe 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ahots-laguntza"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Diru-zorroa"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodeen eskanerra"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desblokeatu"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Gailua blokeatuta dago"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Aurpegia eskaneatzen"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Bidali"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Ezin da ezagutu aurpegia"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Erabili hatz-marka"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetootha konektatuta."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Bateriaren ehunekoa ezezaguna da."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hegaldi-modua"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN eginbidea aktibatuta."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateriaren karga: <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateriak ehuneko <xliff:g id="PERCENTAGE">%1$s</xliff:g> dauka kargatuta. Zure erabilera kontuan izanda, <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen zaizkio."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Kargatzen ari da bateria. Ehuneko <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> arte kargatu da oraingoz."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ikusi jakinarazpen guztiak"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter gaituta."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Tonu-jotzailea dardara moduan."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztirako sarbidea du <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Egin aurrera"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partekatu edo grabatu aplikazioak"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Edukia partekatzeko edo grabatzeko baimena eman nahi diozu aplikazioari?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztirako sarbidea du aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztirako sarbidea du aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin edo bestelako kontuzko informazioarekin."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IKT saileko administratzaileak blokeatu du"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Pantaila-kapturak egiteko aukera desgaituta dago, gailu-gidalerroei jarraikiz"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Garbitu guztiak"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kudeatu"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desblokeatu erabiltzeko"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Pantaila blokeatuaren ezarpenak"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Eskaneatu QR kodea"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Datu-konexioa desaktibatu nahi duzu?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wifi-sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Zure operadorea"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> operadorera aldatu nahi duzu berriro?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Datu-konexioa ez da automatikoki aldatuko erabilgarritasunaren arabera"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ez, eskerrik asko"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Bai, aldatu nahi dut"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakusteko baimena eman nahi diozu <xliff:g id="APP_0">%1$s</xliff:g> aplikazioari?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioaren informazioa irakur dezake."</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> (<xliff:g id="NETWORKMODE">%2$s</xliff:g>)"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Aldi baterako konektatuta"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Konexio ahula"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Ez da automatikoki aktibatuko datu-konexioa"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Konexiorik gabe"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ez dago beste sare erabilgarririk"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index a504720..1a8553c 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"دستیار صوتی"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"کیف پول"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"کدخوان پاسخ‌سریع"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"باز کردن قفل"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"دستگاه قفل است"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"درحال اسکن کردن چهره"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ارسال"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"چهره شناسایی نشد"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"از اثر انگشت استفاده کنید"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوتوث متصل است."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"درصد شارژ باتری مشخص نیست."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"حالت هواپیما."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN روشن است."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"باتری <xliff:g id="NUMBER">%d</xliff:g> درصد."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"باتری <xliff:g id="PERCENTAGE">%1$s</xliff:g> درصد شارژ دارد، براساس مصرفتان تقریباً <xliff:g id="TIME">%2$s</xliff:g> شارژ باقی‌مانده است"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"در حال شارژ باتری، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> درصد"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"دیدن همه اعلان‌ها"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"تله‌تایپ فعال شد."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"زنگ لرزشی."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"وقتی درحال هم‌رسانی، ضبط، یا پخش محتوای برنامه‌ای هستید، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه محتوایی که در آن برنامه نمایان است یا پخش می‌شود دسترسی دارد. بنابراین مراقب گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، یا دیگر اطلاعات حساس باشید."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ادامه"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"هم‌رسانی یا ضبط برنامه"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"به این برنامه اجازه هم‌رسانی یا ضبط می‌دهید؟"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"وقتی درحال هم‌رسانی، ضبط، یا پخش محتوا هستید، این برنامه به همه محتوایی که در صفحه‌تان نمایان است یا در دستگاهتان پخش می‌شود دسترسی دارد. بنابراین مراقب گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، یا دیگر اطلاعات حساس باشید."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"وقتی درحال هم‌رسانی، ضبط، یا پخش محتوای برنامه‌ای هستید، این برنامه به همه محتوایی که در آن برنامه نمایان است یا پخش می‌شود دسترسی دارد. بنابراین مراقب گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، یا دیگر اطلاعات حساس باشید."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"سرپرست فناوری اطلاعات آن را مسدود کرده است"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"«ضبط صفحه‌نمایش» به‌دلیل خط‌مشی دستگاه غیرفعال است"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"پاک کردن همه موارد"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سابقه"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"برای استفاده، قفل را باز کنید"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"هنگام دریافت کارت‌ها مشکلی پیش آمد، لطفاً بعداً دوباره امتحان کنید"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"تنظیمات صفحه قفل"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"اسکن رمزینه پاسخ‌سریع"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"در ساعت <xliff:g id="WHEN">%1$s</xliff:g>، دیگر صدای زنگ ساعت را نمی‌شنوید"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"داده تلفن همراه خاموش شود؟"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"‏نمی‌توانید ازطریق <xliff:g id="CARRIER">%s</xliff:g> به داده یا اینترنت دسترسی داشته باشید. اینترنت فقط ازطریق Wi-Fi در دسترس خواهد بود."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"شرکت مخابراتی شما"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"می‌خواهید به <xliff:g id="CARRIER">%s</xliff:g> برگردید؟"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"وضعیت داده تلفن همراه به‌طور خودکار براساس دردسترس بودن تغییر نخواهد کرد"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"نه متشکرم"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"بله، عوض شود"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"چون برنامه‌ای درحال ایجاد تداخل در درخواست مجوز است، «تنظیمات» نمی‌تواند پاسخ شما را تأیید کند."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"به <xliff:g id="APP_0">%1$s</xliff:g> اجازه داده شود تکه‌های <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد؟"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- می‌تواند اطلاعات <xliff:g id="APP">%1$s</xliff:g> را بخواند"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"موقتاً متصل است"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"اتصال ضعیف"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"داده تلفن همراه به‌طور خودکار متصل نخواهد شد"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"اتصال برقرار نیست"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"شبکه دیگری وجود ندارد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ba8bfe0..12e9797 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ääniapuri"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-koodiskanneri"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Avaa lukitus"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Laite lukittu"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Kasvojen skannaus"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Lähetä"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Kasvoja ei voi tunnistaa"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Käytä sormenjälkeä"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth yhdistetty."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akun varaustaso ei tiedossa."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lentokonetila."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN päällä"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akun virta <xliff:g id="NUMBER">%d</xliff:g> prosenttia."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akkua jäljellä <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosenttia eli noin <xliff:g id="TIME">%2$s</xliff:g> käyttösi perusteella"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Akku latautuu: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosenttia"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Näytä kaikki ilmoitukset"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Tekstipuhelin käytössä."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Soittoääni: värinä."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kun jaat, tallennat tai striimaat sovellusta, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Jatka"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Jaa sovellus tai tallenna sen sisältöä"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Sallitko sovelluksen jakaa tai tallentaa sisältöä?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kun jaat, tallennat tai striimaat sisältöä, sovellus saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kun jaat, tallennat tai striimaat sovellusta, tämä sovellus saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä tai muita arkaluontoisia tietoja."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT-järjestelmänvalvojasi estämä"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Kuvakaappaus on poistettu käytöstä laitekäytännön perusteella"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tyhjennä kaikki"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Muuta asetuksia"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avaa lukitus ja käytä"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukitusnäytön asetukset"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skannaa QR-koodi"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Laitetaanko mobiilidata pois päältä?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> ei enää tarjoa pääsyä dataan eikä internetyhteyttä, joka on saatavilla vain Wi-Fin kautta."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operaattorisi"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Palauta käyttöön <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiilidata ei vaihdu automaattisesti saatavuuden perusteella"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ei kiitos"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Kyllä, vaihda"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Sovellus peittää käyttöoikeuspyynnön, joten Asetukset ei voi vahvistaa valintaasi."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Saako <xliff:g id="APP_0">%1$s</xliff:g> näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Se voi lukea tietoja sovelluksesta <xliff:g id="APP">%1$s</xliff:g>."</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Väliaikaisesti yhdistetty"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Heikko yhteys"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilidata ei yhdisty automaattisesti"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ei yhteyttä"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ei muita verkkoja käytettävissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8b183bf..99e8c7f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Lecteur de code QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Numérisation du visage"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envoyer"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Visage non reconnu"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utiliser l\'empreinte digitale"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la pile inconnu."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"RPV activé."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Pile : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pile chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent (environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie en fonction de votre usage)"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Pile en charge : <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Afficher toutes les notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Téléscripteur activé"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Sonnerie en mode vibreur"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Lorsque vous partagez, enregistrez ou diffusez une application, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est affiché ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages ou toute autre information confidentielle."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuer"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partager ou enregistrer une application"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Autoriser cette application à partager ou à enregistrer?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Lorsque vous partagez, enregistrez ou diffusez, cette application a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages ou toute autre information confidentielle."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Lorsque vous partagez, enregistrez ou diffusez une application, cette application a accès à tout ce qui est affiché ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages ou toute autre information confidentielle."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloquée par votre administrateur informatique"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"La fonctionnalité de capture d\'écran est désactivée par l\'application Device Policy"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Numériser le code QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"lecteur de code QR"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Désactiver les données cellulaires?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Vous n\'aurez pas accès aux données ni à Internet avec <xliff:g id="CARRIER">%s</xliff:g>. Vous ne pourrez accéder à Internet que par Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"votre fournisseur de services"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Rebasculer vers <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Il n\'y aura pas de basculement automatique entre les données mobiles selon la disponibilité"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Non merci"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Oui, basculer"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Une application obscurcit une demande d\'autorisation, alors Paramètres ne peut pas vérifier votre réponse."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher <xliff:g id="APP_2">%2$s</xliff:g> tranches?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Il peut lire de l\'information de <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion faible"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Aucune connexion auto. des données cellulaires"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau n\'est accessible"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f5bcfb3..68fae12 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Lecteur de code QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analyse du visage en cours"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envoyer"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Visage non reconnu"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilisez empreinte digit."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la batterie inconnu."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Le VPN est activé."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batterie : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterie chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent : il reste environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie, selon votre utilisation"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batterie en charge : <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Afficher toutes les notifications"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Téléscripteur activé"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Sonnerie en mode vibreur"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Lorsque vous partagez, enregistrez ou castez une appli, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuer"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partager ou enregistrer une appli"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Autoriser cette appli à partager ou enregistrer ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Lorsque vous partagez, enregistrez ou castez, cette appli a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Lorsque vous partagez, enregistrez ou castez une appli, cette appli a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention à vos mots de passe, détails de mode de paiement, messages ou autres informations sensibles."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloquée par votre administrateur informatique"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"La capture d\'écran est désactivée conformément aux règles relatives à l\'appareil"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scanner un code QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Désactiver les données mobiles ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Vous n\'aurez pas accès aux données mobiles ni à Internet via <xliff:g id="CARRIER">%s</xliff:g>. Vous ne pourrez accéder à Internet que par Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"votre opérateur"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Rebasculer sur <xliff:g id="CARRIER">%s</xliff:g> ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Il n\'y aura pas de basculement automatique entre les données mobile selon la disponibilité"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Non, merci"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Oui, revenir"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"L\'application Paramètres ne peut pas valider votre réponse, car une application masque la demande d\'autorisation."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g> ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Accès aux informations de <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion médiocre"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Pas de connexion automatique des données mobiles"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau disponible"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 4b1809be..fd554ba 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de código QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analizando cara"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Non se recoñeceu a cara"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa a impresión dixital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Descoñécese a porcentaxe da batería."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"A VPN está activada."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Carga da batería: <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, durará <xliff:g id="TIME">%2$s</xliff:g> co uso que adoitas darlle"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batería cargando. Nivel: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> por cento."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas as notificacións"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletipo activado"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Timbre en vibración"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cando compartes, gravas ou emites unha aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir ou gravar unha aplicación"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Queres permitir que esta aplicación comparta ou grave contido?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Cando compartes, gravas ou emites contido, esta aplicación ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Cando compartes, gravas ou emites aplicacións, esta aplicación ten acceso a todo o que se vexa ou se reproduza nelas. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"O teu administrador de TI bloqueou esta aplicación"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A política do dispositivo desactivou a opción de capturar a pantalla"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todas"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración da pantalla de bloqueo"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Escanear código QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Queres desactivar os datos móbiles?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Non terás acceso aos datos nin a Internet a través de <xliff:g id="CARRIER">%s</xliff:g>. Internet só estará dispoñible mediante a wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"o teu operador"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Seguro que queres cambiar de novo a <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"O uso de datos móbiles non cambiará automaticamente en función da dispoñibilidade"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Non, grazas"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Si, cambiar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Dado que unha aplicación se superpón sobre unha solicitude de permiso, a configuración non pode verificar a túa resposta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Queres permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre fragmentos de aplicación de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Pode ler información da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión deficiente"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Os datos móbiles non se conectarán automaticamente"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sen conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Non hai outras redes dispoñibles"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 8174ce7..72c535b 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR કોડ સ્કૅનર"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ચહેરો સ્કૅન કરવો"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"મોકલો"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ચહેરો ઓળખાતો નથી"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"તો ફિંગરપ્રિન્ટ વાપરો"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"બ્લૂટૂથ કનેક્ટ થયું."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"બૅટરીની ટકાવારી અજાણ છે."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"એરપ્લેન મોડ."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ચાલુ છે."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"બૅટરી <xliff:g id="NUMBER">%d</xliff:g> ટકા."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"તમારા વપરાશના આધારે બૅટરી <xliff:g id="PERCENTAGE">%1$s</xliff:g> ટકા, જે લગભગ <xliff:g id="TIME">%2$s</xliff:g> સુધી ચાલે તેટલી બચી છે"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"બૅટરી ચાર્જ થઈ રહી છે, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"બધી સૂચના જુઓ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ટેલિટાઇપરાઇટર સક્ષમ કર્યું."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"રિંગર વાઇબ્રેટ."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"જ્યારે તમે કોઈ ઍપ શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી કોઈપણ વસ્તુનો ઍક્સેસ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ધરાવે છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ અથવા અન્ય સંવેદનશીલ માહિતીની બાબતે સાવચેત રહેશો."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ચાલુ રાખો"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"કોઈ ઍપ શેર કરો અથવા રેકોર્ડ કરો"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"આ ઍપને શેર કે રેકોર્ડ કરવાની મંજૂરી આપીએ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"જ્યારે તમે શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે આ ઍપ પાસે તમારી સ્ક્રીન પર જોઈ શકાતી કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી બધી વસ્તુઓનો ઍક્સેસ હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ અથવા અન્ય સંવેદનશીલ માહિતીની બાબતે સાવચેત રહેશો."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"જ્યારે તમે કોઈ ઍપને શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તેના પર બતાવવામાં કે ચલાવવામાં આવતી બધી વસ્તુઓનો ઍક્સેસ આ ઍપ પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ અથવા અન્ય સંવેદનશીલ માહિતીની બાબતે સાવચેત રહેશો."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"તમારા IT ઍડમિન દ્વારા બ્લૉક કરાયેલી"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ડિવાઇસ પૉલિસી અનુસાર સ્ક્રીન કૅપ્ચર કરવાની સુવિધા બંધ કરવામાં આવી છે"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"બધુ સાફ કરો"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"મેનેજ કરો"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ઇતિહાસ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ઉપયોગ કરવા માટે અનલૉક કરો"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"લૉક સ્ક્રીનના સેટિંગ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR કોડ સ્કૅન કરો"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"તમે <xliff:g id="WHEN">%1$s</xliff:g> એ તમારો આગલો એલાર્મ સાંભળશો નહીં"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"મોબાઇલ ડેટા બંધ કરીએ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"તમને <xliff:g id="CARRIER">%s</xliff:g> મારફતે ડેટા અથવા ઇન્ટરનેટનો ઍક્સેસ મળશે નહીં. ઇન્ટરનેટ માત્ર વાઇ-ફાઇ દ્વારા ઉપલબ્ધ થશે."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"તમારા કૅરિઅર"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> પર પાછા સ્વિચ કરીએ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"મોબાઇલ ડેટાને ઉપલબ્ધતાના આધારે ઑટોમૅટિક રીતે સ્વિચ કરવામાં આવશે નહીં"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ના, આભાર"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"હા, સ્વિચ કરો"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"કોઈ ઍપ પરવાનગી વિનંતીને અસ્પષ્ટ કરતી હોવાને કારણે, સેટિંગ તમારા પ્રતિસાદને ચકાસી શકતું નથી."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>ને <xliff:g id="APP_2">%2$s</xliff:g> સ્લાઇસ બતાવવાની મંજૂરી આપીએ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- મારાથી <xliff:g id="APP">%1$s</xliff:g>ની માહિતી વાંચી શકાતી નથી"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"હંગામી રીતે કનેક્ટ કર્યું"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"નબળું કનેક્શન"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"મોબાઇલ ડેટા ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"કોઈ કનેક્શન નથી"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"બીજાં કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 862ef34..a49c8d0 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"क्यूआर कोड स्कैनर"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"डिवाइस अनलॉक करने के लिए चेहरा स्कैन किया जाता है"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"भेजें"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"चेहरे की पहचान नहीं हुई"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"फ़िंगरप्रिंट इस्तेमाल करें"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट किया गया."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाई जहाज़ मोड."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN चालू."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> प्रति‍शत बैटरी."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत बैटरी बची है और आपके इस्तेमाल के हिसाब से यह <xliff:g id="TIME">%2$s</xliff:g> में खत्म हो जाएगी"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"पूरी सूचनाएं देखें"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"टेलीटाइपराइटर सक्षम."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"रिंगर कंपन (वाइब्रेशन)."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रही हर चीज़ या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"जारी रखें"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"क्या इस ऐप्लिकेशन को शेयर या रिकॉर्ड करने की अनुमति देनी है?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"शेयर, रिकॉर्ड या कास्ट करते समय, इस ऐप्लिकेशन के पास स्क्रीन पर दिख रही हर चीज़ या डिवाइस पर चल रहे सभी मीडिया का ऐक्सेस होता है. इसलिए, इस दौरान पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या दूसरी संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"किसी ऐप्लिकेशन को शेयर, रिकॉर्ड या कास्ट करते समय, इस ऐप्लिकेशन के पास उस ऐप्लिकेशन पर दिख रही हर चीज़ या उस पर चल रहे सभी मीडिया का ऐक्सेस होता है. इसलिए, इस दौरान पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या दूसरी संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"आपके आईटी एडमिन ने स्क्रीन कैप्चर करने की सुविधा पर रोक लगाई है"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"डिवाइस से जुड़ी नीति के तहत स्क्रीन कैप्चर करने की सुविधा बंद है"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सभी को हटाएं"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"मैनेज करें"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"इस्तेमाल करने के लिए, डिवाइस अनलॉक करें"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"क्यूआर कोड स्कैन करें"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"मोबाइल डेटा बंद करना चाहते हैं?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"आप <xliff:g id="CARRIER">%s</xliff:g> से डेटा या इंटरनेट का इस्तेमाल नहीं कर पाएंगे. इंटरनेट सिर्फ़ वाई-फ़ाई से चलेगा."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"आपको मोबाइल और इंटरनेट सेवा देने वाली कंपनी"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"क्या आपको मोबाइल डेटा, <xliff:g id="CARRIER">%s</xliff:g> पर वापस से स्विच करना है?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"उपलब्ध होने पर, मोबाइल डेटा अपने-आप स्विच नहीं होगा"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"स्विच न करें"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"स्विच करें"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ऐप की वजह से मंज़ूरी के अनुरोध को समझने में दिक्कत हो रही है, इसलिए सेटिंग से आपके जवाब की पुष्टि नहीं हो पा रही है."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> को <xliff:g id="APP_2">%2$s</xliff:g> के हिस्से (स्लाइस) दिखाने की मंज़ूरी दें?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- यह <xliff:g id="APP">%1$s</xliff:g> से सूचना पढ़ सकता है"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"इंटरनेट कनेक्शन कुछ समय के लिए है"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"इंटरनेट कनेक्शन खराब है"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा अपने-आप कनेक्ट नहीं होगा"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"इंटरनेट कनेक्शन नहीं है"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"कोई दूसरा नेटवर्क उपलब्ध नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d7fe7d8..71ba52c9 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Čitač QR koda"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključavanje"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Lice nije prepoznato"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Upotrijebite otisak prsta"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth povezan."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak baterije nije poznat."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u zrakoplovu"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> posto."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Pogledajte sve obavijesti"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter je omogućen."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibracija softvera zvona."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kad dijelite, snimate ili emitirate aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Nastavi"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dijeljenje ili snimanje pomoću aplikacije"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Želite li ovoj aplikaciji omogućiti dijeljenje ili bilježenje?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kad dijelite, snimate ili emitirate, ova aplikacija ima pristup svemu što je vidljivo na vašem zaslonu ili se reproducira na vašem uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kad dijelite, snimate ili emitirate aplikaciju, ova aplikacija ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokirao vaš IT administrator"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Snimanje zaslona onemogućeno je u skladu s pravilima za uređaje"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Izbriši sve"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Povijest"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog zaslona"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skeniraj QR kôd"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Čitač QR koda"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Isključiti mobilne podatke?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup mobilnim podacima ili internetu putem operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem Wi-Fija."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vaš mobilni operater"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vratiti se na mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilni podaci neće se automatski prebaciti na temelju dostupnosti"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, hvala"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Da, prebaci"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Budući da aplikacija prekriva zahtjev za dopuštenje, Postavke ne mogu potvrditi vaš odgovor."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Želite li dopustiti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– može čitati informacije aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba veza"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna veza neće se automatski uspostaviti"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 51089e7..d9c438c 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hangsegéd"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kód-szkennelő"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Feloldás"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Az eszköz zárolva van"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Arc keresése"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Küldés"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Az arc nem ismerhető fel"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Használjon ujjlenyomatot"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth csatlakoztatva."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Az akkumulátor töltöttségi szintje ismeretlen."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Repülőgép üzemmód."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN bekapcsolva."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akkumulátor <xliff:g id="NUMBER">%d</xliff:g> százalék."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Az akkumulátor <xliff:g id="PERCENTAGE">%1$s</xliff:g> százalékon áll, a használati adatok alapján körülbelül <xliff:g id="TIME">%2$s</xliff:g> múlva merül le"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Tölt az akkumulátor, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> százalék."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Összes értesítés megtekintése"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter engedélyezve."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Csengő rezeg."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Amikor Ön megoszt, rögzít vagy átküld egy alkalmazást, a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel és más bizalmas információkkal."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Folytatás"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Alkalmazás megosztása és rögzítése"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Engedélyezi ennek az alkalmazásnak a megosztást és a rögzítést?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Amikor Ön megosztást, rögzítést vagy átküldést végez, az alkalmazás a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel és más bizalmas információkkal."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Amikor Ön megoszt, rögzít vagy átküld egy alkalmazást, az alkalmazás az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel és más bizalmas információkkal."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Rendszergazda által letiltva"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A képernyőfelvételt eszközszabályzat tiltja"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Az összes törlése"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kezelés"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Előzmények"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Oldja fel a használathoz"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Probléma merült fel a kártyák lekérésekor, próbálja újra később"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lezárási képernyő beállításai"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR-kód beolvasása"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Kikapcsolja a mobiladatokat?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nem lesz adat-, illetve internet-hozzáférése a <xliff:g id="CARRIER">%s</xliff:g> szolgáltatón keresztül. Az internethez csak Wi-Fi-n keresztül csatlakozhat."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"saját mobilszolgáltató"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Átvált a következőre: <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Nem kerül sor a mobiladat-forgalom automatikus átváltására a rendelkezésre állás alapján"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Most nem"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Igen, átváltok"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Mivel az egyik alkalmazás eltakarja az engedélykérést, a Beállítások alkalmazás nem tudja ellenőrizni az Ön válaszát."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Engedélyezi a(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazásnak, hogy részleteket mutasson a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Információkat olvashat a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazásból"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g>/<xliff:g id="STATE">%1$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ideiglenesen csatlakoztatva"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Gyenge kapcsolat"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nincs automatikus mobiladat-kapcsolat"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nincs kapcsolat"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nincs több rendelkezésre álló hálózat"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index f1d11fb..820b666 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ձայնային հուշումներ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR կոդերի սկաներ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Ապակողպել"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Սարքը կողպված է"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Դեմքի սկանավորում"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Ուղարկել"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Դեմքը չի ճանաչվել"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Օգտագործեք մատնահետք"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-ը միացված է:"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Մարտկոցի լիցքի մակարդակն անհայտ է։"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ավիառեժիմ"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Միացնել VPN-ը։"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$s</xliff:g> տոկոս է և կբավարարի մոտ <xliff:g id="TIME">%2$s</xliff:g>՝ կախված օգտագործման եղանակից:"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Մարտկոցը լիցքավորվում է: Լիցքը <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> տոկոս է:"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Տեսնել բոլոր ծանուցումները"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Հեռատիպը միացված է:"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Թրթռազանգ:"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է դառնում այն ամենը, ինչ ցուցադրվում է կամ նվագարկվում այդ հավելվածում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Շարունակել"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Հավելվածի էկրանի ցուցադրում կամ տեսագրում"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Թույլատրե՞լ այս հավելվածին ցուցադրել կամ տեսագրել էկրանը"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք էկրանը, այս հավելվածին հասանելի է դառնում այն ամենը, ինչ տեսանելի է էկրանին և նվագարկվում է ձեր սարքում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, այս հավելվածին հասանելի է դառնում այն ամենը, ինչ ցուցադրվում է կամ նվագարկվում այդ հավելվածում։ Հիշեք այդ մասին, երբ պատրաստվում եք դիտել կամ մուտքագրել գաղտնաբառեր, վճարային տվյալներ, հաղորդագրություններ և այլ կոնֆիդենցիալ տեղեկություններ։"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Արգելափակվել է ձեր ՏՏ ադմինիստրատորի կողմից"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Էկրանի տեսագրումն անջատված է սարքի կանոնների համաձայն"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Մաքրել բոլորը"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Կառավարել"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Պատմություն"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Սկանավորել QR կոդը"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Անջատե՞լ բջջային ինտերնետը"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> օպերատորի բջջային ինտերնետը հասանելի չի լինի: Համացանցից կկարողանաք  օգտվել միայն Wi-Fi-ի միջոցով:"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Ձեր"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Անցնե՞լ <xliff:g id="CARRIER">%s</xliff:g> ցանցին"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Սարքն ավտոմատ չի անցնի բջջային ինտերնետին"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ոչ, շնորհակալություն"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Այո"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Քանի որ ներածումն արգելափակված է ինչ-որ հավելվածի կողմից, Կարգավորումները չեն կարող հաստատել ձեր պատասխանը:"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Թույլատրե՞լ <xliff:g id="APP_0">%1$s</xliff:g> հավելվածին ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Կարող է կարդալ տեղեկություններ <xliff:g id="APP">%1$s</xliff:g> հավելվածից"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ժամանակավոր կապ"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Թույլ կապ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Բջջային ինտերնետն ավտոմատ չի միանա"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Կապ չկա"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Այլ հասանելի ցանցեր չկան"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ac5abde..a5ff4915 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Pemindai Kode QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Perangkat terkunci"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Memindai wajah"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Kirim"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Tidak mengenali wajah"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan sidik jari"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode pesawat."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktif."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterai <xliff:g id="NUMBER">%d</xliff:g> persen."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterai <xliff:g id="PERCENTAGE">%1$s</xliff:g> persen, sekitar <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Mengisi daya baterai, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> persen."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Lihat semua notifikasi"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter diaktifkan."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Pendering bergetar."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Lanjutkan"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Bagikan atau rekam aplikasi"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Izinkan aplikasi ini membagikan atau merekam?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Jika Anda membagikan, merekam, atau mentransmisikan, aplikasi ini akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, aplikasi ini akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, atau informasi sensitif lainnya."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Diblokir oleh admin IT Anda"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Pengambilan screenshot dinonaktifkan oleh kebijakan perangkat"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hapus semua"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kelola"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histori"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Terjadi error saat mendapatkan kartu Anda, coba lagi nanti"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Pindai kode QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Nonaktifkan data seluler?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Anda tidak akan dapat mengakses data atau internet melalui <xliff:g id="CARRIER">%s</xliff:g>. Internet hanya akan tersedia melalui Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Operator Seluler Anda"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Beralih kembali ke <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Data seluler tidak akan dialihkan secara otomatis berdasarkan ketersediaan"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Lain kali"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ya, alihkan"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Karena sebuah aplikasi menghalangi permintaan izin, Setelan tidak dapat memverifikasi respons Anda."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Izinkan <xliff:g id="APP_0">%1$s</xliff:g> menampilkan potongan <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Dapat membaca informasi dari <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Terhubung sementara"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Koneksi buruk"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data seluler tidak akan terhubung otomatis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tidak ada koneksi"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Jaringan lain tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 40c7d90..bc84dc9 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Raddaðstoð"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Veski"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kóðaskanni"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Taka úr lás"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Tækið er læst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Andlit skannað"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Senda"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Andlit þekkist ekki"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Nota fingrafar í staðinn"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tengt."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Staða rafhlöðu óþekkt."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugstilling"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Kveikt á VPN."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> prósent á rafhlöðu."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Rafhlaða í <xliff:g id="PERCENTAGE">%1$s</xliff:g> prósentum, um það bil <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun þína"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Rafhlaða í hleðslu, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Sjá allar tilkynningar"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Fjarriti virkur."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Titrar við hringingu."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Þegar þú deilir, tekur upp eða sendir út forrit hefur <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Áfram"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deila eða taka upp forrit"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Leyfa þessu forriti að deila eða taka upp?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Þegar þú deilir, tekur upp eða sendir út fær þetta forrit aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Þegar þú deilir, tekur upp eða sendir út forrit hefur viðkomandi forrit aðgang að öllu sem sést eða spilast í forritinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð eða aðrar viðkvæmar upplýsingar."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Útilokað af kerfisstjóra"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Slökkt er á skjáupptöku í tækjareglum"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hreinsa allt"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Stjórna"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ferill"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Taktu úr lás til að nota"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Stillingar fyrir læstan skjá"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skanna QR-kóða"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ekki mun heyrast í vekjaranum <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Viltu slökkva á farsímagögnum?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Þú munt ekki hafa aðgang að gögnum eða internetinu í gegnum <xliff:g id="CARRIER">%s</xliff:g>. Aðeins verður hægt að tengjast internetinu með Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"símafyrirtækið þitt"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Skipta aftur yfir í <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Ekki verður skipt sjálfkrafa á milli farsímagagna byggt á tiltækileika"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nei takk"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Já, skipta"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Stillingar geta ekki staðfest svarið þitt vegna þess að forrit er að fela heimildarbeiðni."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Viltu leyfa <xliff:g id="APP_0">%1$s</xliff:g> að sýna sneiðar úr <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Það getur lesið upplýsingar úr <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tímabundin tenging"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Léleg tenging"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Farsímagögn tengjast ekki sjálfkrafa"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Engin tenging"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Engin önnur net í boði"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 1ebbbd8..0d2c3b1 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Scanner codici QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Sblocca"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloccato"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scansione del viso"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Invia"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Volto non riconosciuto"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa l\'impronta"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth collegato."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modalità aereo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN attiva."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteria: <xliff:g id="NUMBER">%d</xliff:g> percento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Livello della batteria: <xliff:g id="PERCENTAGE">%1$s</xliff:g> percento. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batteria in carica, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Visualizza tutte le notifiche"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Telescrivente abilitata."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Suoneria vibrazione."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quando condividi, registri o trasmetti un\'app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dati di pagamento, messaggi o altre informazioni sensibili."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continua"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Condividi o registra un\'app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Consentire all\'app di condividere o registrare?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Quando condividi, registri o trasmetti, l\'app ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dati di pagamento, messaggi o altre informazioni sensibili."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Quando condividi, registri o trasmetti un\'app, questa app ha accesso a qualsiasi elemento visualizzato o riprodotto su quell\'app. Presta quindi attenzione a password, dati di pagamento, messaggi o altre informazioni sensibili."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloccata dall\'amministratore IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"L\'acquisizione schermo è disattivata dai criteri relativi ai dispositivi"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Cancella tutto"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestisci"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Cronologia"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Sblocca per usare"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Impostazioni schermata di blocco"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scansiona codice QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Non sentirai la tua prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Disattivare i dati mobili?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Non avrai accesso ai dati o a Internet tramite <xliff:g id="CARRIER">%s</xliff:g>. Internet sarà disponibile soltanto tramite Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"il tuo operatore"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vuoi passare nuovamente all\'operatore <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"I dati mobili non passeranno automaticamente all\'operatore in base alla disponibilità"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"No, grazie"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sì, confermo"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Un\'app sta oscurando una richiesta di autorizzazione, pertanto Impostazioni non può verificare la tua risposta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vuoi consentire all\'app <xliff:g id="APP_0">%1$s</xliff:g> di mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Può leggere informazioni dell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessione attiva"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connessione debole"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nessuna connessione dati mobili automatica"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nessuna connessione"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nessun\'altra rete disponibile"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ce8c974..453e8d6 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"האסיסטנט"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ארנק"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"‏סורק קודי QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ביטול נעילה"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"הנעילה מבוטלת"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"המכשיר נעול"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"סורק פנים"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"שליחה"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"לא ניתן לזהות את הפנים"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"שימוש בטביעת אצבע במקום זאת"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"‏Bluetooth מחובר."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"אחוז טעינת הסוללה לא ידוע."</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"מצב טיסה"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN פועל."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> אחוזים של סוללה."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"רמת הטעינה בסוללה: <xliff:g id="PERCENTAGE">%1$s</xliff:g> אחוזים, הזמן הנותר המשוער על סמך השימוש שלך: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"הסוללה בטעינה, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"הצגת כל ההתראות"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"‏TeleTypewriter מופעל"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"צלצול ורטט."</string>
@@ -375,16 +380,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"‏בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"המשך"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"שיתוף או הקלטה של אפליקציה"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"לאפשר לאפליקציה הזו לשתף או להקליט?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"‏בזמן שיתוף, הקלטה או העברה (cast) תהיה לאפליקציה הזו גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. כדאי להיזהר ולא לחשוף סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"‏בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה לאפליקציה הזו גישה לכל מה שמוצג בה או מופעל ממנה. כדאי להיזהר ולא לחשוף סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"‏נחסם על ידי מנהל ה-IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"צילום המסך מושבת בגלל מדיניות המכשיר"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ניקוי הכול"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"היסטוריה"</string>
@@ -500,7 +500,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"יש לבטל את הנעילה כדי להשתמש"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"הגדרות מסך הנעילה"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"‏סריקת קוד QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"לכבות את חבילת הגלישה?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"‏לא תהיה לך גישה לנתונים או לאינטרנט באמצעות <xliff:g id="CARRIER">%s</xliff:g>. אינטרנט יהיה זמין רק באמצעות Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"הספק שלך"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"לחזור אל <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"לא תתבצע החלפה אוטומטית של חבילת הגלישה על סמך זמינות"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"לא, תודה"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"כן, אני רוצה להחליף"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"יש אפליקציה שמסתירה את בקשת ההרשאה, ולכן אין אפשרות לאמת את התשובה בהגדרות."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"האם לאפשר ל-<xliff:g id="APP_0">%1$s</xliff:g> להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- תהיה לה אפשרות לקרוא מידע מאפליקציית <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"מחובר באופן זמני"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"חיבור באיכות ירודה"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"החיבור לנתונים סלולריים לא מתבצע באופן אוטומטי"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"אין חיבור"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"אין רשתות זמינות אחרות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c76b207..7efa1a2 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"音声アシスト"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ウォレット"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR コードスキャナ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ロック解除"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"ロック解除済み"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"デバイスはロックされています"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"顔のスキャン"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"送信"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"顔を認識できません"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"指紋認証をお使いください"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetoothに接続済み。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"バッテリー残量は不明です。"</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"機内モード。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN は ON です。"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"バッテリー残量: <xliff:g id="NUMBER">%d</xliff:g>パーセント"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"バッテリー残量: <xliff:g id="PERCENTAGE">%1$s</xliff:g>、およそ <xliff:g id="TIME">%2$s</xliff:g> にバッテリー切れ(使用状況に基づく)"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"電池充電中: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>パーセント"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"通知をすべて表示"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"テレタイプライターが有効です。"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"バイブレーション着信。"</string>
@@ -375,16 +380,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"アプリの共有、録画、キャスト中は、そのアプリで表示されている内容や再生している内容に <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> がアクセスできるため、パスワード、お支払いの詳細、メッセージなどの機密情報にご注意ください。"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"続行"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"アプリの共有、録画"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"このアプリに共有や録画を許可しますか?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"共有、録画、キャスト中は、画面に表示されている内容やデバイスで再生している内容にこのアプリがアクセスできるため、パスワード、お支払いの詳細、メッセージなどの機密情報にご注意ください。"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"アプリの共有、録画、キャスト中は、そのアプリで表示されている内容や再生している内容にこのアプリがアクセスできるため、パスワード、お支払いの詳細、メッセージなどの機密情報にご注意ください。"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT 管理者によりブロックされました"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"デバイス ポリシーに基づき、画面のキャプチャが無効になりました"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"すべて消去"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"履歴"</string>
@@ -445,7 +445,7 @@
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕のオーバーレイ"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"有効にする"</string>
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"無効にする"</string>
-    <string name="sound_settings" msgid="8874581353127418308">"着信音とバイブレーション"</string>
+    <string name="sound_settings" msgid="8874581353127418308">"サウンドとバイブレーション"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"アプリは固定されています"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [最近] を同時に押し続けると固定が解除されます。"</string>
@@ -500,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ロックを解除して使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ロック画面の設定"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR コードのスキャン"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR コードスキャナ"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
@@ -739,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"モバイルデータを OFF にしますか?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g>でデータやインターネットにアクセスできなくなります。インターネットには Wi-Fi からのみ接続できます。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"携帯通信会社"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> に戻しますか?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"利用可能な場合でも、モバイルデータを利用するよう自動的に切り替わることはありません"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"キャンセル"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"切り替える"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"アプリが許可リクエストを隠しているため、設定側でユーザーの応答を確認できません。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"「<xliff:g id="APP_2">%2$s</xliff:g>」のスライスの表示を「<xliff:g id="APP_0">%1$s</xliff:g>」に許可しますか?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- 「<xliff:g id="APP">%1$s</xliff:g>」からの情報の読み取り"</string>
@@ -929,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"一時的に接続されています"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"接続が不安定です"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"モバイルデータには自動接続しません"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"接続なし"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"利用できるネットワークはありません"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 729951d..292aaa4 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ხმოვანი დახმარება"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"საფულე"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR კოდის სკანერი"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"განბლოკვა"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"მოწყობილობა ჩაკეტილია"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"მიმდინარეობს სახის სკანირება"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"გაგზავნა"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"სახის ამოცნობა შეუძლებ."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"გამოიყენეთ თითის ანაბეჭდი"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth დაკავშირებულია."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ბატარეის პროცენტული მაჩვენებელი უცნობია."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"თვითმფრინავის რეჟიმი"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ჩართულია."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ბატარეა: <xliff:g id="NUMBER">%d</xliff:g> პროცენტი."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ბატარეა <xliff:g id="PERCENTAGE">%1$s</xliff:g> პროცენტზეა, მოხმარების გათვალისწინებით დარჩა დაახლოებით <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ბატარეა იტენება. ამჟამად არის <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> პროცენტი."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ყველა შეტყობინების ნახვა"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ტელეტაიპი ჩართულია."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ვიბრაციის რეჟიმი."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> აქვს წვდომა აქვს ყველაფერზე, რაც ჩანს აპში ან ითამაშეთ. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა მგრძნობიარე ინფორმაციასთან."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"გაგრძელება"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"გააზიარეთ ან ჩაწერეთ აპი"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"გსურთ ამ აპისთვის გაზიარების ან ჩაწერის უფლების მიცემა?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"როდესაც თქვენ აზიარებთ, იწერთ ან ტრანსლირებთ, ამ აპს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა სენსიტიურ ინფორმაციასთან."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"როდესაც თქვენ აზიარებთ, იწერთ ან ტრანსლირებთ, ამ აპს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა სენსიტიურ ინფორმაციასთან."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"დაბლოკილია თქვენი IT-ადმინისტრატორის მიერ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ეკრანის აღბეჭდვა გამორთულია მოწყობილობის წესების თანახმად"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ყველას გასუფთავება"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"მართვა"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ისტორია"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"გამოსაყენებლად განბლოკვა"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ჩაკეტილი ეკრანის პარამეტრები"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR კოდის სკანირება"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR კოდის სკანერი"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"გსურთ მობილური ინტერნეტის გამორთვა?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"თქვენ არ გექნებათ მობილურ ინტერნეტზე ან ზოგადად ინტერნეტზე წვდომა <xliff:g id="CARRIER">%s</xliff:g>-ის მეშვეობით. ინტერნეტი მხოლოდ Wi-Fi-კავშირის მეშვეობით იქნება ხელმისაწვდომი."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"თქვენი ოპერატორი"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"გსურთ ისევ <xliff:g id="CARRIER">%s</xliff:g>-ზე გადართვა?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"მობილური მონაცემების ხელმისაწვდომობის მიხედვით ავტომატური გადართვა არ მოხდება"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"არა, გმადლობთ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"დიახ, გადაირთოს"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ვინაიდან აპი ფარავს ნებართვის მოთხოვნას, პარამეტრების მიერ თქვენი პასუხი ვერ დასტურდება."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"ანიჭებთ ნებართვას <xliff:g id="APP_0">%1$s</xliff:g>-ს, აჩვენოს <xliff:g id="APP_2">%2$s</xliff:g>-ის ფრაგმენტები?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- მას შეუძლია ინფორმაციის <xliff:g id="APP">%1$s</xliff:g>-დან წაკითხვა"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"დროებით დაკავშირებული"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"სუსტი კავშირი"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"მობილურ ინტერნეტს ავტომატურად არ დაუკავშირდება"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"კავშირი არ არის"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"სხვა ქსელები მიუწვდომელია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 9a6530e..bffda32 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дауыс көмекшісі"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR кодын сканерлеу қолданбасы"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Бекітпесін ашу"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Құрылғы құлыпталды."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Бетті сканерлеу"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Жіберу"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Бет танылмады."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Орнына саусақ ізін пайдаланыңыз."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth қосылған."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея зарядының мөлшері белгісіз."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ұшақ режимі."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN қосулы."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарея заряды: <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз. Пайдалануға байланысты шамамен <xliff:g id="TIME">%2$s</xliff:g> уақытқа жетеді."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Батарея зарядталуда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Барлық хабарландыруды қарау"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Телетайп қосылған."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Қоңырау тербелісі."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Қолданба экранын бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасы онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Жалғастыру"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Қолданба экранын бөлісу не жазу"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Қолданбаға бөлісуге не жазып алуға рұқсат берілсін бе?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Экранды бөлісу, жазып алу не трансляциялау кезінде бұл қолданба экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Қолданбаны бөлісу, жазып алу не трансляциялау кезінде бұл қолданба онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізу кезінде сақ болыңыз."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Әкімшіңіз бөгеген"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Құрылғы саясатына байланысты экранды түсіру өшірілді."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Барлығын тазалау"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Басқару"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Тарих"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR кодын сканерлеу"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Келесі <xliff:g id="WHEN">%1$s</xliff:g> дабылыңызды есітпейсіз"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Мобильдік интернет өшірілсін бе?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> операторы арқылы деректерге немесе интернетке кіре алмайсыз. Интернетке тек Wi-Fi арқылы кіресіз."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"операторыңыз"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> операторына қайта ауысу керек пе?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мобильдік интернет операторды қолдану мүмкіндігіне қарай автоматты түрде ауыспайды."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Жоқ, рақмет"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Иә, ауыстырылсын"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Басқа қолданба рұқсат сұрауын жасырып тұрғандықтан, параметрлер жауабыңызды растай алмайды."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> қолданбасына <xliff:g id="APP_2">%2$s</xliff:g> қолданбасының үзінділерін көрсетуге рұқсат берілсін бе?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Бұл <xliff:g id="APP">%1$s</xliff:g> қолданбасындағы ақпаратты оқи алады"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Уақытша байланыс орнатылды."</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыс нашар."</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобильдік интернет автоматты түрде қосылмайды."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыс жоқ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Басқа қолжетімді желі жоқ"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 979c1c3..6d2e5a8 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ជំនួយសំឡេង"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"កម្មវិធីស្កេនកូដ QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ដោះ​​សោ"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"បានចាក់សោ​ឧបករណ៍"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ការ​ស្កេន​មុខ"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ផ្ញើ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"មិនអាចសម្គាល់មុខបានទេ"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ប្រើស្នាមម្រាមដៃជំនួសវិញ​"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"បាន​តភ្ជាប់​ប៊្លូធូស។"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"មិនដឹងអំពី​ភាគរយថ្មទេ។"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"បើក VPN ។"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ថ្ម <xliff:g id="NUMBER">%d</xliff:g> ភាគរយ។"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ថ្ម <xliff:g id="PERCENTAGE">%1$s</xliff:g> ភាគរយ អាចប្រើបាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត ផ្អែក​លើការ​ប្រើប្រាស់​របស់អ្នក"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"កំពុងសាកថ្ម <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ភាគរយ"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"មើល​ការជូនដំណឹង​ទាំងអស់"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ​"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"កម្មវិធី​រោទ៍​ញ័រ។"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬបញ្ជូនកម្មវិធី <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើប្រាស់អ្វីៗដែលបង្ហាញ ឬលេងនៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះពាក្យសម្ងាត់ ព័ត៌មាន​លម្អិតអំពី​ការ​ទូទាត់ប្រាក់ សារ ឬព័ត៌មានរសើបផ្សេងទៀត។"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"បន្ត"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ចែករំលែក ឬថតកម្មវិធី"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"អនុញ្ញាតកម្មវិធីនេះឱ្យចែករំលែក ឬថតឬ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"នៅពេលអ្នក​កំពុងចែករំលែក ថត ឬបញ្ជូន កម្មវិធីនេះ​មានសិទ្ធិចូលប្រើប្រាស់អ្វីៗ​ដែលបង្ហាញឱ្យឃើញនៅលើ​អេក្រង់របស់អ្នក ឬលេងនៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះពាក្យសម្ងាត់ ព័ត៌មាន​លម្អិតអំពី​ការ​ទូទាត់ប្រាក់ សារ ឬព័ត៌មានរសើបផ្សេងទៀត។"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"នៅពេលអ្នក​កំពុងចែករំលែក ថត ឬបញ្ជូន​កម្មវិធី កម្មវិធីនេះ​មានសិទ្ធិចូលប្រើប្រាស់អ្វីៗ​ដែលបង្ហាញ ឬលេងនៅលើ​កម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះ​ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ ឬព័ត៌មានរសើប​ផ្សេងទៀត។"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"បានទប់ស្កាត់ដោយអ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ការថតអេក្រង់ត្រូវបានបិទ​ដោយគោលការណ៍ឧបករណ៍"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"សម្អាត​ទាំងអស់"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"គ្រប់គ្រង"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ប្រវត្តិ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ដោះសោដើម្បីប្រើប្រាស់"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"មានបញ្ហា​ក្នុងការទាញយក​កាត​របស់អ្នក សូម​ព្យាយាមម្ដងទៀត​នៅពេលក្រោយ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ការកំណត់អេក្រង់ចាក់សោ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"ស្កេន​កូដ QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"អ្នកនឹងមិនលឺម៉ោងរោទ៍ <xliff:g id="WHEN">%1$s</xliff:g> បន្ទាប់របស់អ្នកទេ"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"បិទទិន្នន័យទូរសព្ទចល័ត?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"អ្នកនឹង​មិន​មាន​សិទ្ធិ​ចូល​ប្រើទិន្នន័យ​ ឬអ៊ីនធឺណិត​តាមរយៈ <xliff:g id="CARRIER">%s</xliff:g> បានឡើយ។ អ៊ីនធឺណិត​នឹងអាច​ប្រើបាន​តាមរយៈ Wi-Fi តែប៉ុណ្ណោះ។"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ក្រុមហ៊ុន​​សេវាទូរសព្ទរបស់អ្នក"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"ប្ដូរទៅ <xliff:g id="CARRIER">%s</xliff:g> វិញឬ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ទិន្នន័យទូរសព្ទចល័តនឹងមិនប្ដូរដោយស្វ័យប្រវត្តិដោយផ្អែកតាមភាពអាចប្រើបាននោះទេ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ទេ អរគុណ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"បាទ/ចាស ប្ដូរ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ការកំណត់​មិនអាច​ផ្ទៀងផ្ទាត់​ការឆ្លើយតប​របស់អ្នក​បាន​ទេ ដោយសារ​កម្មវិធី​កំពុង​បាំងសំណើ​សុំការ​អនុញ្ញាត។"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"អនុញ្ញាតឱ្យ <xliff:g id="APP_0">%1$s</xliff:g> បង្ហាញ​ស្ថិតិប្រើប្រាស់​របស់ <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- វា​អាច​អាន​ព័ត៌មាន​ពី <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"បានភ្ជាប់ជាបណ្ដោះអាសន្ន"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ការតភ្ជាប់​ខ្សោយ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ទិន្នន័យទូរសព្ទចល័ត​នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"មិនមាន​ការតភ្ជាប់ទេ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"មិន​មាន​បណ្ដាញផ្សេងទៀតដែល​អាច​ប្រើ​បានទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 48270a6..099139f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ವಾಲೆಟ್"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್‌ಲಾಕ್"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ಕಳುಹಿಸಿ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ಬ್ಲೂಟೂತ್‌‌ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ಏರೋಪ್ಲೇನ್‌ ಮೋಡ್‌"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ನಲ್ಲಿ VPN"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ಬ್ಯಾಟರಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರತಿಶತ."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಬ್ಯಾಟರಿಯು ಪ್ರತಿಶತ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ರಷ್ಟು ಮತ್ತು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ಬ್ಯಾಟರಿ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ಪ್ರತಿಶತ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಿ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ಟೆಲಿಟೈಪ್‌ರೈಟರ್ ಸಕ್ರಿಯವಾಗಿದೆ."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ರಿಂಗರ್ ವೈಬ್ರೇಟ್‌."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಬಿತ್ತರಿಸುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ಮುಂದುವರಿಸಿ"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ಹಂಚಿಕೊಳ್ಳಲು ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಬಿತ್ತರಿಸುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ ಈ ಆ್ಯಪ್ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ನೀವು ಆ್ಯಪ್ ಒಂದನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಬಿತ್ತರಿಸುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಈ ಆ್ಯಪ್ ಹೊಂದಿರುತ್ತದೆ. ಹಾಗಾಗಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಇತರ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ನಿರ್ಬಂಧಿಸಿದ್ದಾರೆ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ಸಾಧನ ನೀತಿಯಿಂದ ಸ್ಕ್ರೀನ್ ಕ್ಯಾಪ್ಚರಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ಇತಿಹಾಸ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ಬಳಸಲು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ಲಾಕ್ ಸ್ಕ್ರ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್ ಮಾಡಬೇಕೆ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"ನೀವು <xliff:g id="CARRIER">%s</xliff:g> ಮೂಲಕ ಡೇಟಾ ಅಥವಾ ಇಂಟರ್ನೆಟ್‌ಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುವುದಿಲ್ಲ. ಇಂಟರ್ನೆಟ್, ವೈ-ಫೈ ಮೂಲಕ ಮಾತ್ರ ಲಭ್ಯವಿರುತ್ತದೆ."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ನಿಮ್ಮ ವಾಹಕ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> ಗೆ ಬದಲಿಸುವುದೇ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ಲಭ್ಯತೆಯ ಆಧಾರದ ಮೇಲೆ ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಬದಲಾಗುವುದಿಲ್ಲ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ಬೇಡ, ಧನ್ಯವಾದಗಳು"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ಹೌದು, ಬದಲಿಸಿ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ಅನುಮತಿ ವಿನಂತಿಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಮರೆಮಾಚುತ್ತಿರುವ ಕಾರಣ, ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> ಸ್ಲೈಸ್‌ಗಳನ್ನು ತೋರಿಸಲು <xliff:g id="APP_0">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ಇದು <xliff:g id="APP">%1$s</xliff:g> ನಿಂದ ಮಾಹಿತಿಯನ್ನು ಓದಬಹುದು"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ತಾತ್ಕಾಲಿಕವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ಕಳಪೆ ಸಂಪರ್ಕ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ಯಾವುದೇ ಕನೆಕ್ಷನ್ ಇಲ್ಲ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ಇತರ ಯಾವುದೇ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index dab98eb..9e3d6c3 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"음성 지원"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"월렛"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 코드 스캐너"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"잠금 해제"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"기기 잠김"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"얼굴 스캔 중"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"보내기"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"얼굴을 인식할 수 없습니다."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"대신 지문을 사용하세요."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"블루투스가 연결되었습니다."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"배터리 잔량을 알 수 없습니다."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"비행기 모드입니다."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 켜짐"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"배터리 <xliff:g id="NUMBER">%d</xliff:g>퍼센트"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"배터리 <xliff:g id="PERCENTAGE">%1$s</xliff:g>퍼센트, 평소 사용량 기준 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"배터리 충전 중, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%입니다."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"모든 알림 보기"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"전신 타자기(TTY)가 사용 설정되었습니다."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"벨소리가 진동입니다."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"앱을 공유하거나 녹화하거나 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"계속"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"앱 공유 또는 녹화"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"앱에서 공유하거나 기록하도록 허용하시겠습니까?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"공유하거나 녹화하거나 전송할 때 이 앱에서 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"앱을 공유하거나 녹화하거나 전송할 때는 이 앱에서 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT 관리자에 의해 차단됨"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"기기 정책에 의해 화면 캡처가 사용 중지되었습니다."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"모두 지우기"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"관리"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"기록"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"잠금 해제하여 사용"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"잠금 화면 설정"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR 코드 스캔"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"모바일 데이터를 사용 중지하시겠습니까?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g>을(를) 통해 데이터 또는 인터넷에 액세스할 수 없게 됩니다. 인터넷은 Wi-Fi를 통해서만 사용할 수 있습니다."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"이동통신사"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"다시 <xliff:g id="CARRIER">%s</xliff:g>(으)로 전환할까요?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"모바일 데이터가 가용성에 따라 자동으로 전환하지 않습니다."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"나중에"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"예, 전환합니다"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"앱이 권한 요청을 가리고 있기 때문에 설정에서 내 응답을 확인할 수 없습니다."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하도록 허용하시겠습니까?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g>의 정보를 읽을 수 있음"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"일시적으로 연결됨"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"연결 상태 나쁨"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"모바일 데이터가 자동으로 연결되지 않음"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"연결되지 않음"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"사용 가능한 다른 네트워크가 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index a3c98ce..bfa6bb8 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Үн жардамчысы"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Капчык"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR коддорунун сканери"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Кулпусун ачуу"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Түзмөк кулпуланды"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Жүз скандалууда"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Жөнөтүү"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Жүз таанылбай жатат"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Манжа изин колдонуңуз"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth байланышта"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Учак тартиби."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN күйүк."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батареянын деңгээли <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз, колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Батарея кубатталууда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Бардык билдирмелерди көрүү"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ТелеТайп терүүсү жандырылган."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Шыңгыраганда титирөө."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Бөлүшүп, жаздырып же тышкы экранда бөлүшкөндө <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ал колдонмодо көрүнүп жана ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөм маалыматын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Улантуу"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Колдонмону бөлүшүү же жаздыруу"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Бул колдонмого бөлүшүп же жаздырууга уруксат бересизби?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Бөлүшүп, жаздырып же тышкы экранга чыгарганда бул колдонмо экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Бөлүшүп, жаздырып же тышкы экранга чыгарганда бул колдонмо ал колдонмодо көрсөтүлүп жана ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT администраторуңуз бөгөттөп койгон"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Түзмөк саясаты экрандагыны тартып алууну өчүрүп койгон"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Баарын тазалап салуу"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Башкаруу"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Таржымал"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Колдонуу үчүн кулпусун ачыңыз"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экранды кулпулоо параметрлери"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR кодун скандоо"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки эскертмени укпайсыз"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Мобилдик Интернетти өчүрөсүзбү?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> байланыш оператору аркылуу Интернетке кире албай каласыз. Интернетке Wi-Fi аркылуу гана кирүүгө болот."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"байланыш операторуңуз"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Кайра <xliff:g id="CARRIER">%s</xliff:g> байланыш операторуна которуласызбы?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Жеткиликтүү болгондо мобилдик Интернет автоматтык түрдө которулбайт"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Жок, рахмат"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ооба, которулуу"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Жөндөөлөр жообуңузду ырастай албай жатат."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосуна <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөтүүгө уруксат берилсинби?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунун маалыматын окуйт"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Убактылуу туташып турат"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Байланыш начар"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилдик трафик автоматтык түрдө туташтырылбайт"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыш жок"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Башка тармактар жеткиликсиз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 862cd52..e3a9079 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"ຕົວສະແກນລະຫັດ QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ການສະແກນໜ້າ"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ສົ່ງ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ໂໝດໃນຍົນ."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ເປີດ."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ແບັດເຕີຣີ <xliff:g id="NUMBER">%d</xliff:g> ເປີເຊັນ."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ແບັດເຕີຣີ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ເປີເຊັນ, ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ກຳລັງສາກແບັດເຕີຣີ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ເປີເຊັນ."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ເບິ່ງການແຈ້ງເຕືອນທັງໝົດ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter ຖືກເປີດຢູ່."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ສັ່ນເຕືອນພ້ອມສຽງເອີ້ນເຂົ້າ."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ໃນຕອນທີ່ທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານແອັບ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ມີສິດເຂົ້າເຖິງສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ໃນແອັບນັ້ນ. ດັ່ງນັ້ນໃຫ້ລະມັດລະວັງກ່ຽວກັບລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ ຫຼື ຂໍ້ມູນທີ່ລະອຽດອ່ອນອື່ນໆ."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ສືບຕໍ່"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ແບ່ງປັນ ຫຼື ບັນທຶກແອັບ"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ອະນຸຍາດໃຫ້ແອັບນີ້ແບ່ງປັນ ຫຼື ບັນທຶກບໍ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານ, ແອັບນີ້ຈະມີສິດເຂົ້າເຖິງສິ່ງທີ່ເຫັນໄດ້ໃນໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນໃຫ້ລະມັດລະວັງເລື່ອງລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ ຫຼື ຂໍ້ມູນທີ່ລະອຽດອ່ອນອື່ນໆ."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ໃນຕອນທີ່ທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານແອັບ, ແອັບນີ້ຈະມີສິດເຂົ້າເຖິງສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ໃນແອັບນັ້ນ. ດັ່ງນັ້ນໃຫ້ລະມັດລະວັງກ່ຽວກັບລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ ຫຼື ຂໍ້ມູນທີ່ລະອຽດອ່ອນອື່ນໆ."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ຖືກບລັອກໄວ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ການຖ່າຍຮູບໜ້າຈໍຖືກປິດການນຳໃຊ້ໄວ້ໂດຍນະໂຍບາຍອຸປະກອນ"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ລຶບລ້າງທັງໝົດ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ຈັດການ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ປະຫວັດ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ປົດລັອກເພື່ອໃຊ້"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"ສະແກນລະຫັດ QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອ​ບິນ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ທ່ານ​ຈະ​ບໍ່​ໄດ້​ຍິນ​ສຽງ​ໂມງ​ປ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ປິດອິນເຕີເນັດມືຖືໄວ້ບໍ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"ທ່ານຈະບໍ່ມີສິດເຂົ້າເຖິງຂໍ້ມູນ ຫຼື ອິນເຕີເນັດຜ່ານ <xliff:g id="CARRIER">%s</xliff:g>. ອິນເຕີເນັດຈະສາມາດໃຊ້ໄດ້ຜ່ານ Wi-Fi ເທົ່ານັ້ນ."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ຂອງ​ທ່ານ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"ສະຫຼັບກັບໄປໃຊ້ <xliff:g id="CARRIER">%s</xliff:g> ບໍ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ອິນເຕີເນັດມືຖືຈະບໍ່ປ່ຽນຕາມຄວາມພ້ອມໃຫ້ບໍລິການໂດຍອັດຕະໂນມັດ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ບໍ່, ຂອບໃຈ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ແມ່ນແລ້ວ, ສະຫຼັບ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ເນື່ອງຈາກມີແອັບໃດໜຶ່ງກຳລັງຂັດຂວາງການຂໍອະນຸຍາດ, ການຕັ້ງຄ່າຈຶ່ງບໍ່ສາມາດຢັ້ງຢືນການຕອບຮັບຂອງທ່ານໄດ້."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"ອະນຸຍາດ <xliff:g id="APP_0">%1$s</xliff:g> ໃຫ້ສະແດງ <xliff:g id="APP_2">%2$s</xliff:g> ສະໄລ້ບໍ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ມັນສາມາດອ່ານຂໍ້ມູນຈາກ <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ເຊື່ອມຕໍ່ແລ້ວຊົ່ວຄາວ"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ສັນຍານເຊື່ອມຕໍ່ຊ້າ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ຈະບໍ່ເຊື່ອມຕໍ່ອິນເຕີເນັດມືຖືອັດຕະໂນມັດ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ບໍ່ມີການເຊື່ອມຕໍ່"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ບໍ່ມີເຄືອຂ່າຍອື່ນທີ່ສາມາດໃຊ້ໄດ້"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 0b13747..7daedbd 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodų skaitytuvas"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Nuskaitomas veidas"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Siųsti"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Veidas neatpažintas"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Naudoti piršto antspaudą"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"„Bluetooth“ prijungtas."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumuliatoriaus energija procentais nežinoma."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lėktuvo režimas."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN įjungtas."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akumuliatorius: <xliff:g id="NUMBER">%d</xliff:g> proc."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> proc. akumuliatoriaus energijos – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>, atsižvelgiant į naudojimą"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Įkraunamas akumuliatorius, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Žr. visus pranešimus"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"„TeleTypewriter“ įgalinta."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibracija skambinant."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kai bendrinate, įrašote ar perduodate turinį, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali pasiekti viską, kas rodoma ar leidžiama programoje. Todėl būkite atsargūs su slaptažodžiais, išsamia mokėjimo metodo informacija, pranešimais ar kita neskelbtina informacija."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Tęsti"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Programos bendrinimas ar įrašymas"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Leisti šiai programai bendrinti arba įrašyti?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kai bendrinate, įrašote ar perduodate turinį, ši programa gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs su slaptažodžiais, išsamia mokėjimo metodo informacija, pranešimais ar kita neskelbtina informacija."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kai bendrinate, įrašote ar perduodate turinį, ši programa gali pasiekti viską, kas rodoma ar leidžiama programoje. Todėl būkite atsargūs su slaptažodžiais, išsamia mokėjimo metodo informacija, pranešimais ar kita neskelbtina informacija."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Užblokavo jūsų IT administratorius"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ekrano fiksavimo funkcija išjungta vadovaujantis įrenginio politika"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Viską išvalyti"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Tvarkyti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Atrakinti, kad būtų galima naudoti"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Gaunant korteles kilo problema, bandykite dar kartą vėliau"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Užrakinimo ekrano nustatymai"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR kodo nuskaitymas"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Išjungti mobiliojo ryšio duomenis?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Naudodamiesi „<xliff:g id="CARRIER">%s</xliff:g>“ paslaugomis neturėsite galimybės pasiekti duomenų arba interneto. Internetą galėsite naudoti tik prisijungę prie „Wi-Fi“."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"savo operatoriaus"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Perjungti atgal į „<xliff:g id="CARRIER">%s</xliff:g>“?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiliojo ryšio duomenys nebus automatiškai perjungti atsižvelgiant į pasiekiamumą"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, ačiū"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Taip, perjungti"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Kadangi programa užstoja leidimo užklausą, nustatymuose negalima patvirtinti jūsų atsakymo."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Leisti „<xliff:g id="APP_0">%1$s</xliff:g>“ rodyti „<xliff:g id="APP_2">%2$s</xliff:g>“ fragmentus?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Gali nuskaityti informaciją iš „<xliff:g id="APP">%1$s</xliff:g>“"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Laikinai prijungta"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Prastas ryšys"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Naud. mob. r. duomenis nebus autom. prisijungiama"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nėra ryšio"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nėra kitų pasiekiamų tinklų"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e90a0a4..d431233 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Balss palīgs"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Maks"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Kvadrātkoda skeneris"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Atbloķēt"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Ierīce ir bloķēta"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sejas skenēšana"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Sūtīt"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Nevar atpazīt seju"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Lietot pirksta nospiedumu"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth savienojums ir izveidots."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumulatora uzlādes līmenis procentos nav zināms."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lidmašīnas režīms."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ieslēgts"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procenti. Ņemot vērā lietojumu, atlikušais laiks ir apmēram <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Skatīt visus paziņojumus"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletaips ir iespējots."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvana signāls — vibrācija."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Lietotnes kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Turpināt"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Lietotnes kopīgošana vai ierakstīšana"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vai atļaut šai lietotnei kopīgot vai ierakstīt?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kopīgošanas, ierakstīšanas vai apraides laikā šī lietotne var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kopīgošanas, ierakstīšanas vai apraides laikā lietotne var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem un citu sensitīvu informāciju."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloķējis jūsu IT administrators"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ierīces politika ir atspējojusi ekrānuzņēmumu izveidi"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Dzēst visu"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pārvaldīt"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Vēsture"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lai izmantotu, atbloķējiet ekrānu"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Bloķēšanas ekrāna iestatījumi"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Kvadrātkoda skenēšana"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vai izslēgt mobilos datus?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Izmantojot mobilo sakaru operatora <xliff:g id="CARRIER">%s</xliff:g> pakalpojumus, nevarēsiet piekļūt datiem vai internetam. Internetam varēsiet piekļūt, tikai izmantojot Wi-Fi savienojumu."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"jūsu mobilo sakaru operators"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vai pārslēgties atpakaļ uz operatoru <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilie dati netiks automātiski pārslēgti, pamatojoties uz pieejamību."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nē, paldies"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Jā, pārslēgties"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Lietotne Iestatījumi nevar verificēt jūsu atbildi, jo cita lietotne aizsedz atļaujas pieprasījumu."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vai atļaut lietotnei <xliff:g id="APP_0">%1$s</xliff:g> rādīt lietotnes <xliff:g id="APP_2">%2$s</xliff:g> sadaļas?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Var lasīt informāciju no lietotnes <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Īslaicīgi izveidots savienojums"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Vājš savienojums"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilo datu savienojums netiks veidots automātiski"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nav savienojuma"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nav pieejams neviens cits tīkls"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 454d58d..de4ae1e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помош"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Скенер на QR-кодови"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Отклучување"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Уредот е заклучен"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лице"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Испрати"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Не се препознава ликот"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користи отпечаток"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е поврзан."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентот на батеријата е непознат."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Авионски режим."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN е вклучена."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија <xliff:g id="NUMBER">%d</xliff:g> проценти."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија <xliff:g id="PERCENTAGE">%1$s</xliff:g> отсто, уште околу <xliff:g id="TIME">%2$s</xliff:g> според вашето користење"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Полнење на батеријата, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> отсто."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Видете ги сите известувања"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Овозможен е телепринтер."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ѕвонче на вибрации."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Кога споделувате, снимате или емитувате апликација, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки или други чувствителни податоци."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Продолжи"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Споделете или снимете апликација"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Да се дозволи апликацијава да споделува или снима?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Кога споделувате, снимате или емитувате, апликацијава има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки или други чувствителни податоци."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Кога споделувате, снимате или емитувате апликација, апликацијава има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки или други чувствителни податоци."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Блокирано од IT-администраторот"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Снимањето на екранот е оневозможено со правила на уредот"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Избриши сѐ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управувајте"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Историја"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отклучете за да користите"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Имаше проблем при преземањето на картичките. Обидете се повторно подоцна"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Поставки за заклучен екран"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Скенирајте QR-код"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Скенер на QR-кодови"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Нема да го слушнете следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Да се исклучи мобилниот интернет?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Нема да имате пристап до податоците или интернетот преку <xliff:g id="CARRIER">%s</xliff:g>. Интернетот ќе биде достапен само преку Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"вашиот оператор"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Да се префрли на <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мобилниот интернет нема автоматски да се префрли според достапноста"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Не, фала"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Да, префрли се"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Бидејќи апликацијата го прикрива барањето за дозвола, „Поставките“ не може да го потврдат вашиот одговор."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Да се дозволи <xliff:g id="APP_0">%1$s</xliff:g> да прикажува делови од <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Може да чита информации од <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено поврзано"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слаба интернет-врска"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилниот интернет не може да се поврзе автоматски"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нема интернет-врска"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нема други достапни мрежи"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index cb9d469..e92ebea 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്‌സ് സഹായം"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR കോഡ് സ്കാനർ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"അണ്‍ലോക്ക് ചെയ്യുക"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"മുഖം സ്കാൻ ചെയ്യുന്നു"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"അയയ്ക്കുക"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"മുഖം തിരിച്ചറിയാനാകുന്നില്ല"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ബ്ലൂടൂത്ത് കണക്‌റ്റുചെയ്തു."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ഫ്ലൈറ്റ് മോഡ്."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ഓണാണ്."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ബാറ്ററി <xliff:g id="NUMBER">%d</xliff:g> ശതമാനം."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ബാറ്ററി <xliff:g id="PERCENTAGE">%1$s</xliff:g> ശതമാനം, നിങ്ങളുടെ ഉപയോഗത്തിൻ്റെ അടിസ്ഥാനത്തിൽ ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> സമയം കൂടി ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ബാറ്ററി ചാർജ് ചെയ്യുന്നു, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"എല്ലാ അറിയിപ്പുകളും കാണുക"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter പ്രവർത്തനക്ഷമമാണ്."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"റിംഗർ വൈബ്രേറ്റ് ചെയ്യുന്നു."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"തുടരുക"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ഒരു ആപ്പ് പങ്കിടുക അല്ലെങ്കിൽ റെക്കോർഡ് ചെയ്യുക"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"പങ്കിടാനോ റെക്കോർഡ് ചെയ്യാനോ ഈ ആപ്പിനെ അനുവദിക്കണോ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, ഈ ആപ്പിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, ഈ ആപ്പിന് ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ, പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ അല്ലെങ്കിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട മറ്റു വിവരങ്ങൾ എന്നിവ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"നിങ്ങളുടെ ഐടി അഡ്‌മിൻ ബ്ലോക്ക് ചെയ്‌തു"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ഉപകരണ നയം, സ്ക്രീൻ ക്യാപ്‌ചർ ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"എല്ലാം മായ്‌ക്കുക"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"മാനേജ് ചെയ്യുക"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ചരിത്രം"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്‌നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR കോഡ് സ്‌കാൻ ചെയ്യുക"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"മൊബൈൽ ഡാറ്റ ഓഫാക്കണോ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"നിങ്ങൾക്ക് ഡാറ്റയിലേക്ക് ആക്‌സസോ അല്ലെങ്കിൽ <xliff:g id="CARRIER">%s</xliff:g> മുഖേനയുള്ള ഇന്റർനെറ്റോ ഉണ്ടാകില്ല. വൈഫൈ മുഖേന മാത്രമായിരിക്കും ഇന്റർനെറ്റ് ലഭ്യത."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"നിങ്ങളുടെ കാരിയർ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> എന്നതിലേക്ക് വീണ്ടും മാറണോ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ലഭ്യതയുടെ അടിസ്ഥാനത്തിൽ, മൊബൈൽ ഡാറ്റ സ്വയമേവ മാറില്ല"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"വേണ്ട"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ഉവ്വ്, മാറുക"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"അനുമതി അഭ്യർത്ഥനയെ ഒരു ആപ്പ് മറയ്‌ക്കുന്നതിനാൽ, ക്രമീകരണത്തിന് നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ഇതിന് <xliff:g id="APP">%1$s</xliff:g>-ൽ നിന്ന് വിവരങ്ങൾ വായിക്കാനാകും"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"താൽക്കാലികമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ദുർബലമായ കണക്ഷൻ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"മൊബൈൽ ഡാറ്റ സ്വയം കണക്റ്റ് ചെയ്യില്ല"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"കണക്ഷനില്ല"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"മറ്റ് നെറ്റ്‌വർക്കുകളൊന്നും ലഭ്യമല്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6e5421c..005a041 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR код сканнер"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скан хийх нүүр царай"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Илгээх"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Царайг танихгүй байна"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Оронд нь хурууны хээ ашиглах"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth холбогдсон."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарейн хувь тодорхойгүй байна."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Нислэгийн горим"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN асаалттай байна."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батарей <xliff:g id="NUMBER">%d</xliff:g> хувьтай."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарей <xliff:g id="PERCENTAGE">%1$s</xliff:g> хувьтай байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Батарейг цэнэглэж байна, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Бүх мэдэгдлийг харах"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter идэвхтэй болов."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Хонхны чичиргээ."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Таныг хуваалцаж, бичиж эсвэл дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь тухайн апп дээр харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж эсвэл бусад эмзэг мэдээлэлд болгоомжтой хандаарай."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Үргэлжлүүлэх"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Хуваалцах эсвэл бичих апп"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Энэ аппад хуваалцах эсвэл бичихийг зөвшөөрөх үү?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Таныг хуваалцаж, бичиж эсвэл дамжуулж байх үед энэ апп нь таны дэлгэц дээр харагдаж буй аливаа зүйл эсвэл төхөөрөмж дээр тань тоглуулж буй зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж эсвэл бусад эмзэг мэдээлэлд болгоомжтой хандаарай."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Таныг хуваалцаж, бичиж эсвэл дамжуулж байх үед энэ апп нь тухайн апп дээр харуулж эсвэл тоглуулж буй аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж эсвэл бусад эмзэг мэдээлэлд болгоомжтой хандаарай."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Таны IT админ блоклосон"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Төхөөрөмжийн бодлогоор дэлгэцийн зураг авахыг идэвхгүй болгосон"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Бүгдийг арилгах"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Удирдах"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Түүх"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ашиглахын тулд түгжээг тайлах"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR код скан хийх"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR код сканнер"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Мобайл датаг унтраах уу?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Та <xliff:g id="CARRIER">%s</xliff:g>-р дата эсвэл интернэтэд хандах боломжгүй болно. Интернэтэд зөвхөн Wi-Fi-р холбогдох боломжтой болно."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"таны оператор компани"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> руу буцаан сэлгэх үү?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мобайл дата нь боломжтой эсэхэд тулгуурлан автоматаар сэлгэхгүй"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Үгүй, баярлалаа"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Тийм, сэлгэе"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Апп нь зөвшөөрлийн хүсэлтийг танихгүй байгаа тул Тохиргооноос таны хариултыг баталгаажуулах боломжгүй байна."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>-д <xliff:g id="APP_2">%2$s</xliff:g>-н хэсгүүдийг (slices) харуулахыг зөвшөөрөх үү?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Энэ нь <xliff:g id="APP">%1$s</xliff:g>-с мэдээлэл унших боломжтой"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Түр зуур холбогдсон"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Холболт сул байна"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобайл дата автоматаар холбогдохгүй"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Холболт алга"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Өөр боломжтой сүлжээ байхгүй байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d3723c2..2810cb7 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR कोड स्कॅनर"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करा"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"डिव्हाइस लॉक केले"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"चेहरा स्कॅन करत आहे"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"पाठवा"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"चेहरा ओळखू शकत नाही"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"त्याऐवजी फिंगरप्रिंट वापरा"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्‍ट केले."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"विमान मोड."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सुरू."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"बॅटरी <xliff:g id="NUMBER">%d</xliff:g> टक्के."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"बॅटरी <xliff:g id="PERCENTAGE">%1$s</xliff:g> टक्के, तुमच्या वापराच्या आधारावर सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"बॅटरी चार्ज होत आहे, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> टक्के."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"सर्व सूचना पहा"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter सक्षम केले."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"रिंगर व्हायब्रेट."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"तुम्ही अ‍ॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"पुढे सुरू ठेवा"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"अ‍ॅप शेअर किंवा रेकॉर्ड करा"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"या अ‍ॅपला शेअर किंवा रेकॉर्ड करण्याची अनुमती द्यायची आहे का?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"तुम्ही शेअर, रेकॉर्ड किंवा कास्ट करत असता, तेव्हा या अ‍ॅपला तुमच्या स्क्रीनवर दाखवलेल्या अथवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज किंवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"तुम्ही अ‍ॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, या अ‍ॅपला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज अथवा इतर संवेदनशील माहिती काळजीपूर्वक वापरा."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"तुमच्या आयटी ॲडमिनने ब्लॉक केले आहे"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"डिव्हाइस धोरणाने स्‍क्रीन कॅप्‍चर करणे बंद केले आहे"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सर्व साफ करा"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थापित करा"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"वापरण्यासाठी अनलॉक करा"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन सेटिंग्ज"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR कोड स्कॅन करा"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"तुम्ही तुमचा <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा पुढील अलार्म ऐकणार नाही"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"मोबाइल डेटा बंद करायचा?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"तुम्हाला <xliff:g id="CARRIER">%s</xliff:g> मधून डेटा किंवा इंटरनेटचा अ‍ॅक्सेस नसेल. इंटरनेट फक्त वाय-फाय मार्फत उपलब्ध असेल."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"तुमचा वाहक"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> वर परत स्विच करायचे आहे का?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"उपलब्धतेच्या आधारावर मोबाइल डेटा आपोआप स्विच होणार नाही"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"नाही, नको"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"होय, स्विच करा"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"अ‍ॅप परवानगी विनंती अस्पष्‍ट करत असल्‍याने, सेटिंग्ज तुमचा प्रतिसाद पडताळू शकत नाहीत."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> ला <xliff:g id="APP_2">%2$s</xliff:g> चे तुकडे दाखवण्याची अनुमती द्यायची का?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ते <xliff:g id="APP">%1$s</xliff:g> ची माहिती वाचू शकते"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"तात्पुरते कनेक्ट केलेले"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"खराब कनेक्शन"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा ऑटो-कनेक्ट होणार नाही"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"कोणतेही कनेक्शन नाही"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"इतर कोणतेही नेटवर्क उपलब्ध नाहीत"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b9bbbb3..1d82ec0 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Pengimbas Kod QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Peranti dikunci"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Mengimbas wajah"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Hantar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Tak dapat mengecam wajah"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan cap jari"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth disambungkan."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Peratusan kuasa bateri tidak diketahui."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod pesawat"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN dihidupkan."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateri <xliff:g id="NUMBER">%d</xliff:g> peratus."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateri <xliff:g id="PERCENTAGE">%1$s</xliff:g> peratus, tinggal kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan anda"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateri mengecas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> peratus."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Lihat semua pemberitahuan"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Mesin Teletaip didayakan."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Pendering bergetar."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Apabila anda berkongsi, merakam atau menghantar apl, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mempunyai akses kepada apa-apa yang dipaparkan atau dimainkan pada apl tersebut. Jadi berhati-hati dengan kata laluan, butiran pembayaran, mesej atau maklumat sensitif lain."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Teruskan"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Kongsi atau rakam apl"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Benarkan apl ini berkongsi atau merakam?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Apabila anda berkongsi, merakam atau menghantar, apl ini mempunyai akses kepada apa-apa yang boleh dilihat pada skrin anda atau dimainkan pada peranti anda. Jadi berhati-hati dengan kata laluan, butiran pembayaran, mesej atau maklumat sensitif lain."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Apabila anda berkongsi, merakam atau menghantar apl, apl ini mempunyai akses kepada apa-apa yang dipaparkan atau dimainkan pada apl tersebut. Jadi berhati-hati dengan kata laluan, butiran pembayaran, mesej atau maklumat sensitif lain."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Disekat oleh pentadbir IT anda"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Tangkapan skrin dilumpuhkan oleh dasar peranti"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Kosongkan semua"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Urus"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Sejarah"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Terdapat masalah sewaktu mendapatkan kad anda. Sila cuba sebentar lagi"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Tetapan skrin kunci"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Imbas kod QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Pengimbas kod QR"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Matikan data mudah alih?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Anda tidak akan mempunyai akses kepada data atau Internet melalui <xliff:g id="CARRIER">%s</xliff:g>. Internet hanya tersedia melaui Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"pembawa anda"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Tukar kembali kepada <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Data mudah alih tidak akan ditukar secara automatik berdasarkan ketersediaan"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Tidak perlu"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ya, tukar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Oleh sebab apl melindungi permintaan kebenaran, Tetapan tidak dapat mengesahkan jawapan anda."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Benarkan <xliff:g id="APP_0">%1$s</xliff:g> menunjukkan <xliff:g id="APP_2">%2$s</xliff:g> hirisan?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Hos hirisan boleh membaca maklumat daripada <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Disambungkan buat sementara waktu"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Sambungan lemah"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data mudah alih tidak akan autosambung"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tiada sambungan"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Tiada rangkaian lain yang tersedia"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 69f45be..f79e32f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"အသံ အကူအညီ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ကုဒ်ဖတ်စနစ်"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"သော့ဖွင့်ရန်"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"စက်ပစ္စည်းကို လော့ခ်ချထားသည်"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"မျက်နှာ စကင်ဖတ်နေသည်"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ပို့ရန်"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"မျက်နှာကို မမှတ်မိပါ"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"လက်ဗွေကို အစားထိုးသုံးပါ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ကို ဖွင့်ထားသည်။"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ဘက်ထရီ <xliff:g id="NUMBER">%d</xliff:g> ရာခိုင်နှုန်း။"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ရာခိုင်နှုန်း၊ သင်၏ အသုံးပြုမှုအပေါ် မူတည်၍ <xliff:g id="TIME">%2$s</xliff:g> ခန့်ကျန်သည်"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ဘက်ထရီအားသွင်းနေသည်၊ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%။"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"သတိပေးချက်များအားလုံးကို ကြည့်ရန်"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter ရရှိသည်။"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"တုန်ခါခြင်း ဖုန်းမြည်သံ"</string>
@@ -215,7 +221,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"ဖန်သားပြင် အနေအထားက အလျားလိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"ဖန်သားပြင် အနေအထားက ဒေါင်လိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်"</string>
     <string name="dessert_case" msgid="9104973640704357717">"မုန့်ထည့်သော ပုံး"</string>
-    <string name="start_dreams" msgid="9131802557946276718">"ဖန်သားပြင်အသုံးပြုမှု ချွေတာမှုစနစ်"</string>
+    <string name="start_dreams" msgid="9131802557946276718">"စခရင်နားချိန်"</string>
     <string name="ethernet_label" msgid="2203544727007463351">"အီသာနက်"</string>
     <string name="quick_settings_dnd_label" msgid="7728690179108024338">"မနှောင့်ယှက်ရ"</string>
     <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ဘလူးတုသ်"</string>
@@ -229,7 +235,7 @@
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"အော်တို-လည်"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"မျက်နှာပြင်အား အလိုအလျောက်လှည့်ခြင်း"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"တည်နေရာ"</string>
-    <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"စကရင်ချွေတာစနစ်"</string>
+    <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"စကရင်နားချိန်"</string>
     <string name="quick_settings_camera_label" msgid="5612076679385269339">"ကင်မရာသုံးခွင့်"</string>
     <string name="quick_settings_mic_label" msgid="8392773746295266375">"မိုက်သုံးခွင့်"</string>
     <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"ရနိုင်သည်"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"အက်ပ်ဖြင့် မျှဝေ၊ ရိုက်ကူး (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် ၎င်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားအရေးကြီးအချက်အလက်များနှင့်ပတ်သက်၍ ဂရုစိုက်ပါ။"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ရှေ့ဆက်ရန်"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"အက်ပ် မျှဝေခြင်း (သို့) ရိုက်ကူးခြင်း"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ဤအက်ပ်ကို မျှဝေ (သို့) ရိုက်ကူး ခွင့်ပြုမလား။"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"မျှဝေ၊ ရိုက်ကူး (သို့) ကာစ်လုပ်သည့်အခါ ဤအက်ပ်သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားသတိထားရမည့် အချက်အလက်များနှင့် ပတ်သက်၍ သတိပြုပါ။"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"အက်ပ်ဖြင့် မျှဝေ၊ ရိုက်ကူး (သို့) ကာစ်လုပ်သည့်အခါ ဤအက်ပ်သည် ၎င်းတွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ် (သို့) အခြားသတိထားရမည့် အချက်အလက်များနှင့်ပတ်သက်၍ သတိပြုပါ။"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"သင်၏ IT စီမံခန့်ခွဲသူက ပိတ်ထားသည်"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ကိရိယာဆိုင်ရာ မူဝါဒက ဖန်သားပြင်ပုံဖမ်းခြင်းကို ပိတ်ထားသည်"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံးရှင်းရန်"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"မှတ်တမ်း"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"သုံးရန် လော့ခ်ဖွင့်ပါ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR ကုဒ် စကင်ဖတ်ခြင်း"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> ၌သင့်နောက်ထပ် နှိုးစက်ကို ကြားမည်မဟုတ်ပါ"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"မိုဘိုင်းဒေတာ ပိတ်မလား။"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> မှတစ်ဆင့် ဒေတာ သို့မဟုတ် အင်တာနက်ကို မသုံးနိုင်ပါ။ Wi-Fi ဖြင့်သာ အင်တာနက် သုံးနိုင်သည်။"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"သင်၏ ဝန်ဆောင်မှုပေးသူ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> သို့ ပြန်ပြောင်းမလား။"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ရနိုင်မှုပေါ် အခြေခံပြီး မိုဘိုင်းဒေတာကို အလိုအလျောက် မပြောင်းပါ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"မလိုပါ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ပြောင်းရန်"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"အပလီကေးရှင်းတစ်ခုက ခွင့်ပြုချက်တောင်းခံမှုကို ပိတ်ထားသောကြောင့် ဆက်တင်များသည် သင်၏ လုပ်ဆောင်ကို တုံ့ပြန်နိုင်ခြင်းမရှိပါ။"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> အား <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များ ပြသခွင့်ပြုပါသလား။"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ၎င်းသည် <xliff:g id="APP">%1$s</xliff:g> မှ အချက်အလက်ကို ဖတ်နိုင်သည်"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ယာယီချိတ်ဆက်ထားသည်"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ချိတ်ဆက်မှုအားနည်းသည်"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"မိုဘိုင်းဒေတာ အော်တိုမချိတ်ပါ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ချိတ်ဆက်မှုမရှိပါ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"အခြားကွန်ရက်များ မရှိပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7a1b05c..bbd5dc9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Talehjelp"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kodeskanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås opp"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten er låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanning av ansikt"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansiktet gjenkjennes ikke"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bruk fingeravtrykk"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth er tilkoblet."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriprosenten er ukjent."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flymodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN på."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri – <xliff:g id="NUMBER">%d</xliff:g> prosent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterinivået er <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosent – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår basert på bruken din"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batteriet lades – <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Se alle varslene"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter er aktivert."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibreringsmodus."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Når du deler, tar opp eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsett"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Del eller ta opp en app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vil du tillate at denne appen deler eller tar opp?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Når du deler, tar opp eller caster noe, har denne appen tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Når du deler, tar opp eller caster en app, har denne appen tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med passord, betalingsopplysninger, meldinger og annen sensitiv informasjon."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokkert av IT-administratoren"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Skjermdumper er deaktivert av enhetsinnstillingene"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Fjern alt"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Logg"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås opp for å bruke"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Det oppsto et problem med henting av kortene. Prøv på nytt senere"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Innstillinger for låseskjermen"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skann QR-koden"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vil du slå av mobildata?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Du får ikke tilgang til data eller internett via <xliff:g id="CARRIER">%s</xliff:g>. Internett er bare tilgjengelig via Wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operatøren din"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vil du bytte tilbake til <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Det byttes ikke mobildataoperatør automatisk basert på tilgjengelighet"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nei takk"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, bytt"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Fordi en app skjuler tillatelsesforespørselen, kan ikke Innstillinger bekrefte svaret ditt."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vil du tillate at <xliff:g id="APP_0">%1$s</xliff:g> viser <xliff:g id="APP_2">%2$s</xliff:g>-utsnitt?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Den kan lese informasjon fra <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Koblet til midlertidig"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dårlig forbindelse"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobildata kobler ikke til automatisk"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen tilkobling"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ingen andre nettverk er tilgjengelige"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index df70c0d..3baf1de 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR कोड स्क्यानर"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"अनुहार स्क्यान गर्दै"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"पठाउनुहोस्"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"अनुहार पहिचान गर्न सकिएन"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लुटुथ जडान भयो।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाइजहाज मोड।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सक्रिय छ।"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ब्याट्री <xliff:g id="NUMBER">%d</xliff:g> प्रतिशत"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ब्याट्रीको चार्ज <xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत छ, तपाईंको प्रयोगका आधारमा <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ब्याट्री चार्ज हुँदैछ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत भयो।"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"सबै सूचनाहरू हेर्नुहोस्"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"टेलि टाइपराइटर सक्षम गरियो।"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"बज्ने कम्पन हुन्छ।"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"जारी राख्नुहोस्"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"सेयर वा रेकर्ड गर्नका लागि एप चयन गर्नुहोस्"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"यो एपलाई सेयर गर्न वा रेकर्ड गर्न दिने हो?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"यो एपले तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले रेकर्ड गर्दा पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा यो एपले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिएका सबै कुरा खिच्न सक्छ। त्यसैले पासवर्ड, भुक्तानीको विवरण, म्यासेज वा अन्य संवेदनशील जानकारी सुरक्षित राख्नुहोला।"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"तपाईंका सूचना प्रविधि व्यवस्थापकले ब्लक गर्नुभएको छ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"डिभाइसको नीतिका कारण स्क्रिन क्याप्चर गर्ने सुविधा अफ गरिएको छ"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सबै हटाउनुहोस्"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR कोड स्क्यान गर्नुहोस्"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"मोबाइल डेटा निष्क्रिय पार्ने हो?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"तपाईं <xliff:g id="CARRIER">%s</xliff:g> मार्फत डेटा वा इन्टरनेट प्रयोग गर्न सक्नुहुने छैन। Wi-Fi मार्फत मात्र इन्टरनेट उपलब्ध हुने छ।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"तपाईंको सेवा प्रदायक"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"फेरि <xliff:g id="CARRIER">%s</xliff:g> को मोबाइल डेटा अन गर्ने हो?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"मोबाइल डेटा उपलब्धताका आधारमा स्वतः बदलिँदैन"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"पर्दैन, धन्यवाद"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"हुन्छ, बदल्नुहोस्"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"कुनै एपको कारणले अनुमतिसम्बन्धी अनुरोध बुझ्न गाह्रो भइरहेकोले सेटिङहरूले तपाईंको प्रतिक्रिया प्रमाणित गर्न सक्दैनन्।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> लाई <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन अनुमति दिने हो?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- यसले <xliff:g id="APP">%1$s</xliff:g> बाट जानकारी पढ्न सक्छ"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"केही समयका लागि मोबाइल डेटामा कनेक्ट गरिएको छ"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"इन्टरनेट राम्री चलेको छैन"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा स्वतः कनेक्ट हुँदैन"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"इन्टरनेट छैन"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"अन्य नेटवर्क उपलब्ध छैनन्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 1debee4..84d5b6d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portemonnee"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-codescanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontgrendelen"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gezicht scannen"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Verzenden"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Gezicht niet herkend"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Vingerafdruk gebruiken"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-verbinding ingesteld."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterijpercentage onbekend."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN staat aan."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batterij: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterij op <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> op basis van je gebruik"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batterij wordt opgeladen, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%% procent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Alle meldingen bekijken"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter staat aan."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Belsoftware trilt."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Als je deelt, opneemt of cast, heeft <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met wachtwoorden, betalingsgegevens, berichten en andere gevoelige informatie."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Doorgaan"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"App delen of opnemen"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Deze app toestaan om te delen of op te nemen?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Als je deelt, opneemt of cast, heeft deze app toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met wachtwoorden, betalingsgegevens, berichten en andere gevoelige informatie."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Als je deelt, opneemt of cast, heeft deze app toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met wachtwoorden, betalingsgegevens, berichten en andere gevoelige informatie."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Geblokkeerd door je IT-beheerder"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Schermopname staat uit vanwege apparaatbeleid"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Alles wissen"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Beheren"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geschiedenis"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR-code scannen"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobiele data uitzetten?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Je hebt dan geen toegang meer tot data of internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet is alleen nog beschikbaar via wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"je provider"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Terugschakelen naar <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobiele data worden niet automatisch overgezet op basis van beschikbaarheid"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nee, bedankt"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, overschakelen"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Aangezien een app een rechtenverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> toestaan om segmenten van <xliff:g id="APP_2">%2$s</xliff:g> te tonen?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Deze kan informatie lezen van <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tijdelijk verbonden"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Matige verbinding"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data maakt niet automatisch verbinding"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen andere netwerken beschikbaar"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index b444228..433170e 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍‌ ସହାୟକ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ୱାଲେଟ୍"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR କୋଡ ସ୍କାନର"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ଅନଲକ୍‌ କରନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ପଠାନ୍ତୁ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ଫେସ ଚିହ୍ନଟ ହୋଇପାରିବ ନାହିଁ"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ବ୍ଲୁଟୂଥ୍‍‌ ସଂଯୋଗ କରାଯାଇଛି।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍‌।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ଅନ୍‍।"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ବ୍ୟାଟେରୀ <xliff:g id="NUMBER">%d</xliff:g> ଶତକଡ଼ା।"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ବ୍ୟାଟେରୀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ଶତକଡା, ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ପାଖାପାଖି <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ବ୍ୟାଟେରୀ ଚାର୍ଜ ହେଉଛି, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ଶତକଡ଼ା।"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ସମସ୍ତ ବିଜ୍ଞପ୍ତି ଦେଖନ୍ତୁ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ଟେଲି-ଟାଇପରାଇଟର୍ ସକ୍ଷମ ଅଛି।"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ରିଙ୍ଗର୍‌ କମ୍ପନରେ ଅଛି।"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ ସେହି ଆପର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ଜାରି ରଖନ୍ତୁ"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ଏକ ଆପକୁ ସେୟାର କିମ୍ବା ରେକର୍ଡ କରନ୍ତୁ"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ସେୟାର କିମ୍ବା ରେକର୍ଡ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦେବେ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ଆପଣ ସେୟାର, ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ ଏହି ଆପର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ଆପଣ ସେୟାର, ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ ଏହି ଆପର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ କିମ୍ବା ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ସୂଚନା ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ଦ୍ୱାରା ବ୍ଲକ କରାଯାଇଛି"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ଡିଭାଇସ ନୀତି ଦ୍ୱାରା ସ୍କ୍ରିନ କେପଚରିଂକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ଇତିହାସ"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR କୋଡ ସ୍କାନ କରନ୍ତୁ"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR କୋଡ ସ୍କାନର"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ମୋବାଇଲ୍‌ ଡାଟା ବନ୍ଦ କରିବେ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"ଡାଟା କିମ୍ବା ଇଣ୍ଟରନେଟ୍‌କୁ <xliff:g id="CARRIER">%s</xliff:g> ଦ୍ଵାରା ଆପଣଙ୍କର  ଆକ୍ସେସ୍ ରହିବ ନାହିଁ। ଇଣ୍ଟରନେଟ୍‌ କେବଳ ୱାଇ-ଫାଇ ମାଧ୍ୟମରେ ଉପଲବ୍ଧ ହେବ।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ଆପଣଙ୍କ କେରିଅର୍"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g>କୁ ପୁଣି ସ୍ୱିଚ କରିବେ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ଉପଲବ୍ଧତା ଆଧାରରେ ମୋବାଇଲ ଡାଟା ସ୍ୱଚାଳିତ ଭାବେ ସ୍ୱିଚ ହେବ ନାହିଁ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ନା, ଧନ୍ୟବାଦ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ହଁ, ସ୍ୱିଚ କରନ୍ତୁ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ଗୋଟିଏ ଆପ୍‍ ଏକ ଅନୁମତି ଅନୁରୋଧକୁ ଦେଖିବାରେ ବାଧା ଦେଉଥିବାରୁ, ସେଟିଙ୍ଗ ଆପଣଙ୍କ ଉତ୍ତରକୁ ଯାଞ୍ଚ କରିପାରିବ ନାହିଁ।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP_0">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ଏହା <xliff:g id="APP">%1$s</xliff:g>ରୁ ସୂଚନାକୁ ପଢ଼ିପାରିବ"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ଅସ୍ଥାୟୀ ରୂପେ କନେକ୍ଟ କରାଯାଇଛି"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ଦୁର୍ବଳ କନେକ୍ସନ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ମୋବାଇଲ ଡାଟା ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ସଂଯୋଗ ନାହିଁ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ଅନ୍ୟ କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 1633c3b..ed4988f 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ਕੋਡ ਸਕੈਨਰ"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ਅਣਲਾਕ ਕਰੋ"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ਚਿਹਰਾ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ਭੇਜੋ"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ਏਅਰਪਲੇਨ ਮੋਡ।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ਚਾਲੂ ਹੈ।"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"ਬੈਟਰੀ <xliff:g id="NUMBER">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ ਹੈ।"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ਬੈਟਰੀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ਫ਼ੀਸਦ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ ਹੋ ਗਈ।"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ਟੈਲੀ ਟਾਈਪਰਾਈਟਰ ਸਮਰਥਿਤ।"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ਰਿੰਗਰ ਥਰਥਰਾਹਟ।"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰੋ ਜਾਂ ਰਿਕਾਰਡ ਕਰੋ"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"ਕੀ ਇਸ ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਜਾਂ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, ਇਸ ਐਪ ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, ਇਸ ਐਪ ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ ਜਾਂ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ਡੀਵਾਈਸ ਨੀਤੀ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨ ਕੈਪਚਰ ਕਰਨਾ ਬੰਦ ਹੈ"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ਇਤਿਹਾਸ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR ਕੋਡ ਸਕੈਨ ਕਰੋ"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ਕੀ ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ ਕਰਨਾ ਹੈ?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"ਤੁਸੀਂ <xliff:g id="CARRIER">%s</xliff:g> ਰਾਹੀਂ ਡਾਟੇ ਜਾਂ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕਰ ਸਕੋਗੇ। ਇੰਟਰਨੈੱਟ ਸਿਰਫ਼ ਵਾਈ-ਫਾਈ ਰਾਹੀਂ ਉਪਲਬਧ ਹੋਵੇਗਾ।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ਤੁਹਾਡਾ ਕੈਰੀਅਰ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"ਕੀ ਵਾਪਸ <xliff:g id="CARRIER">%s</xliff:g> \'ਤੇ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ਮੋਬਾਈਲ ਡਾਟਾ ਉਪਲਬਧਤਾ ਦੇ ਆਧਾਰ \'ਤੇ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਸਵਿੱਚ ਨਹੀਂ ਹੋਵੇਗਾ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ਹਾਂ, ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"ਕਿਸੇ ਐਪ ਵੱਲੋਂ ਇਜਾਜ਼ਤ ਬੇਨਤੀ ਨੂੰ ਢਕੇ ਜਾਣ ਕਾਰਨ ਸੈਟਿੰਗਾਂ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"ਕੀ <xliff:g id="APP_0">%1$s</xliff:g> ਨੂੰ <xliff:g id="APP_2">%2$s</xliff:g> ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੇਣੇ ਹਨ?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ਇਹ <xliff:g id="APP">%1$s</xliff:g> ਵਿੱਚੋਂ ਜਾਣਕਾਰੀ ਪੜ੍ਹ ਸਕਦਾ ਹੈ"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ਕੁਝ ਸਮੇਂ ਲਈ ਕਨੈਕਟ ਹੈ"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"ਖਰਾਬ ਕਨੈਕਸ਼ਨ"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ਮੋਬਾਈਲ ਡਾਟਾ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ਕੋਈ ਹੋਰ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fca76c4..47b68b1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asystent głosowy"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portfel"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skaner kodów QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Odblokuj"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Urządzenie zablokowane"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanowanie twarzy"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Wyślij"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Nie można rozpoznać twarzy"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Użyj odcisku palca"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth połączony."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Poziom naładowania baterii jest nieznany."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Tryb samolotowy."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Sieć VPN włączona."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, jeszcze <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Ładuję baterię, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Zobacz wszystkie powiadomienia"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Dalekopis (TTY) włączony."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Dzwonek z wibracjami."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Dalej"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Udostępnianie i nagrywanie za pomocą aplikacji"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Zezwolić tej aplikacji na udostępnianie lub nagrywanie?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Podczas udostępniania, nagrywania lub przesyłania treści ta aplikacja ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Podczas udostępniania, nagrywania lub przesyłania treści ta aplikacja ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Zablokowane przez administratora IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Zrzuty ekranu są wyłączone zgodnie z zasadami dotyczącymi urządzeń"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Usuń wszystkie"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Zarządzaj"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odblokuj, aby użyć"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Podczas pobierania kart wystąpił problem. Spróbuj ponownie później."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ustawienia ekranu blokady"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Zeskanuj kod QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nie usłyszysz swojego następnego alarmu <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Wyłączyć mobilną transmisję danych?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nie będziesz mieć dostępu do transmisji danych ani internetu w <xliff:g id="CARRIER">%s</xliff:g>. Internet będzie dostępny tylko przez Wi‑Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"Twój operator"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Wrócić do operatora <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilna transmisja danych nie będzie automatycznie przełączana na podstawie dostępności"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nie, dziękuję"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Tak, wróć"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Aplikacja Ustawienia nie może zweryfikować Twojej odpowiedzi, ponieważ inna aplikacja zasłania prośbę o udzielenie uprawnień."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Zezwolić aplikacji <xliff:g id="APP_0">%1$s</xliff:g> na pokazywanie wycinków z aplikacji <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Może odczytywać informacje z aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tymczasowe połączenie"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Słabe połączenie"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna transmisja danych nie połączy się automatycznie"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Brak połączenia"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Brak innych dostępnych sieci"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 9a3bfa6..4ff823a 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de código QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Rosto não reconhecido"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateria carregando: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas as notificações"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTYpewriter ativado."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibração da campainha."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis na tela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens ou outras informações sensíveis."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartilhar ou gravar um app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Permitir que este app compartilhe ou grave a tela?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Quando você compartilha, grava ou transmite a tela, este app tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens e outras informações sensíveis."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Quando você compartilha, grava ou transmite a tela, este app tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens e outras informações sensíveis."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Ação bloqueada pelo administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A captura de tela foi desativada pela política do dispositivo"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Ler código QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Desativar os dados móveis?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Você não terá acesso a dados ou à Internet pela operadora <xliff:g id="CARRIER">%s</xliff:g>. A Internet só estará disponível via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"sua operadora"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Voltar para a operadora <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"A conexão de dados móveis não vai ser alternada automaticamente de acordo com a disponibilidade"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Agora não"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sim, voltar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dcddba8..a50624e 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistente de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de códigos QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"Desbloqueado"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"A analisar o rosto…"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Imposs. reconhecer rosto"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usar impressão digital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ligado."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentagem da bateria desconhecida."</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo de avião"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria a <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria a <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, resta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g> com base na sua utilização."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateria a carregar (<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%)."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas as notificações"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletipo ativado."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Campainha em vibração."</string>
@@ -375,16 +380,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quando está a partilhar, gravar ou transmitir uma app, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Partilhe ou grave uma app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Permitir que esta app partilhe ou grave?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Quando está a partilhar, gravar ou transmitir, esta app tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Quando está a partilhar, gravar ou transmitir uma app, esta app tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com palavras-passe, detalhes de pagamento, mensagens ou outras informações confidenciais."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bloqueado pelo administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A captura de ecrã está desativada pela política do dispositivo"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerir"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
@@ -500,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para utilizar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao obter os seus cartões. Tente mais tarde."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Definições do ecrã de bloqueio"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Leia o código QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Leitor de códigos QR"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Não vai ouvir o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Desativar os dados móveis?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Não terá acesso a dados ou à Internet através do operador <xliff:g id="CARRIER">%s</xliff:g>. A Internet estará disponível apenas por Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"o seu operador"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Mudar de novo para <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Os dados móveis não vão mudar automaticamente com base na disponibilidade"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Não"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sim, mudar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Uma vez que uma app está a ocultar um pedido de autorização, as Definições não conseguem validar a sua resposta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Permitir que a app <xliff:g id="APP_0">%1$s</xliff:g> mostre partes da app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Pode ler informações da app <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ligado temporariamente"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Ligação fraca"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem ligação automática com dados móveis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem ligação"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 9a3bfa6..4ff823a 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de código QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Rosto não reconhecido"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateria carregando: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Ver todas as notificações"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTYpewriter ativado."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibração da campainha."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis na tela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens ou outras informações sensíveis."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartilhar ou gravar um app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Permitir que este app compartilhe ou grave a tela?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Quando você compartilha, grava ou transmite a tela, este app tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens e outras informações sensíveis."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Quando você compartilha, grava ou transmite a tela, este app tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens e outras informações sensíveis."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Ação bloqueada pelo administrador de TI"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A captura de tela foi desativada pela política do dispositivo"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Ler código QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Desativar os dados móveis?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Você não terá acesso a dados ou à Internet pela operadora <xliff:g id="CARRIER">%s</xliff:g>. A Internet só estará disponível via Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"sua operadora"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Voltar para a operadora <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"A conexão de dados móveis não vai ser alternada automaticamente de acordo com a disponibilidade"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Agora não"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Sim, voltar"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexão fraca"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5825089..e281e88 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistent vocal"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portofel"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Scanner de coduri QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Deblochează"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispozitiv blocat"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanarea chipului"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Trimite"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Chip nerecunoscut"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Folosește amprenta"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Conectat prin Bluetooth."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procentajul bateriei este necunoscut."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod Avion."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Rețea VPN activată"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterie: <xliff:g id="NUMBER">%d</xliff:g> la sută."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Procentul rămas din baterie este <xliff:g id="PERCENTAGE">%1$s</xliff:g>. În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateria se încarcă, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> la sută."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Vezi toate notificările"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter activat."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibrare sonerie."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice se afișează pe ecran sau se redă în aplicație. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuă"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Permite accesul la o aplicație sau înregistreaz-o"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Permiți trimiterea sau înregistrarea din aplicație?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Când permiți accesul, înregistrezi sau proiectezi, aplicația are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, aceasta are acces la orice se afișează pe ecran sau se redă în aplicație. Ai grijă cu parolele, detaliile de plată, mesajele sau alte informații sensibile."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blocată de administratorul IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Capturile de ecran sunt dezactivate de politica privind dispozitivele"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Șterge toate notificările"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionează"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istoric"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Deblochează pentru a folosi"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"A apărut o problemă la preluarea cardurilor. Încearcă din nou mai târziu"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setările ecranului de blocare"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Scanează codul QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Scanner de coduri QR"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nu vei auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Dezactivezi datele mobile?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nu vei avea acces la date sau la internet prin intermediul <xliff:g id="CARRIER">%s</xliff:g>. Internetul va fi disponibil numai prin Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operatorul tău"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Revii la <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Comutarea la datele mobile nu se va face automat în funcție de disponibilitate"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nu, mulțumesc"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Da, fac trecerea"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Deoarece o aplicație acoperă o solicitare de permisiune, Setările nu îți pot verifica răspunsul."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Permiți ca <xliff:g id="APP_0">%1$s</xliff:g> să afișeze porțiuni din <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Poate citi informații din <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectat temporar"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexiune slabă"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nu se conectează automat la date mobile"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nicio conexiune"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nu sunt disponibile alte rețele"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index b6b0628..b7f10f2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Аудиоподсказки"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кошелек"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Сканер QR-кодов"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблокировать."</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройство заблокировано"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканирование лица"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Отправить"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Лицо не распознано."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Используйте отпечаток."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-соединение установлено."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Уровень заряда батареи в процентах неизвестен."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим полета."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Режим VPN включен."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд батареи в процентах: <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Заряд батареи в процентах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Оценка оставшегося времени работы: <xliff:g id="TIME">%2$s</xliff:g>."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Зарядка батареи. Текущий заряд: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Показать все уведомления"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Телетайп включен."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Вибровызов."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когда вы демонстрируете, транслируете экран или записываете видео с него, приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Далее"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Демонстрация экрана или запись видео с него"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Разрешить приложению демонстрировать экран или записывать видео с него?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Когда вы демонстрируете, транслируете экран или записываете видео с него, это приложение получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Когда вы демонстрируете, транслируете экран или записываете видео с него, это приложение получает доступ ко всему, что видно и воспроизводится на экране устройства. Помните об этом, если соберетесь вводить или просматривать пароли, платежные данные, сообщения и другую конфиденциальную информацию."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Заблокировано вашим администратором"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Запись экрана отключена в соответствии с правилами для устройства."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Очистить все"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Настроить"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Сканировать QR-код"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Отключить мобильный Интернет?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Вы не сможете передавать данные или выходить в Интернет через оператора \"<xliff:g id="CARRIER">%s</xliff:g>\". Интернет будет доступен только по сети Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ваш оператор"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Переключиться на сеть \"<xliff:g id="CARRIER">%s</xliff:g>\"?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мобильный интернет не будет переключаться автоматически."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Нет"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Да"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Невозможно принять ваше согласие, поскольку запрос скрыт другим приложением."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Разрешить приложению \"<xliff:g id="APP_0">%1$s</xliff:g>\" показывать фрагменты приложения \"<xliff:g id="APP_2">%2$s</xliff:g>\"?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Ему станут доступны данные из приложения \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Временное подключение"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Слабый сигнал"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Без автоподключения к мобильному интернету"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нет подключения к интернету"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нет других доступных сетей"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 832c211..f9a6b0b 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"හඬ සහාය"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR කේත ස්කෑනරය"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"අඟුල අරින්න"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"උපාංගය අගුලු දමා ඇත"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"මුහුණ ස්කෑන් කිරීම"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"යවන්න"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"මුහුණ හඳුනා ගත නොහැක"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"බ්ලූටූත් සම්බන්ධිතයි."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"බැටරි ප්‍රතිශතය නොදනී."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"අහස්යානා ආකාරය."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ක්‍රියාත්මකයි."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"බැටරි ප්‍රතිශතය <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"බැටරි ප්‍රතිශතය <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ඔබේ භාවිතයට අනුව <xliff:g id="TIME">%2$s</xliff:g> ක් පමණ ඉතුරුයි"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"බැටරිය ආරෝපණය කරමින්, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"සියලු දැනුම්දීම් බලන්න"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter ක්‍රියාත්මකයි."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"හඬ නඟනය කම්පනය වේ."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ඉදිරියට යන්න"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"යෙදුමක් බෙදා ගන්න හෝ පටිගත කරන්න"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"මෙම යෙදුම බෙදා ගැනීමට හෝ පටිගත කිරීමට ඉඩ දෙන්න ද?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"ඔබ බෙදා ගන්නා විට, පටිගත කරන විට, හෝ විකාශය කරන විට, හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. එබැවින් මුරපද, ගෙවීම් විස්තර, පණිවිඩ හෝ වෙනත් සංවේදී තොරතුරු සමග ප්‍රවේශම් වන්න."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ඔබේ IT පරිපාලක විසින් අවහිර කර ඇත"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"උපාංග ප්‍රතිපත්තිය මගින් තිර ග්‍රහණය කිරීම අබල කර ඇත"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"සියල්ල හිස් කරන්න"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"කළමනාකරණය කරන්න"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ඉතිහාසය"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"භාවිත කිරීමට අගුලු හරින්න"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"අගුලු තිර සැකසීම්"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR කේතය ස්කෑන් කරන්න"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්‍රකාරය"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> නොඇසෙනු ඇත"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ජංගම දත්ත ක්‍රියාවිරහිත කරන්නද?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"ඔබට <xliff:g id="CARRIER">%s</xliff:g> හරහා දත්ත හෝ අන්තර්ජාලයට පිවිසීමේ හැකියාවක් නැත. අන්තර්ජාලය Wi-Fi හරහා පමණක් ලබා ගත හැකිය."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ඔබගේ වාහකය"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> වෙත ආපසු මාරු කරන්නද?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"ජංගම දත්ත ලබා ගත හැකි වීමට අනුව ස්වයංක්‍රීයව මාරු නොවෙයි"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"එපා ස්තුතියි"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ඔව්, මාරු කරන්න"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"යෙදුමක් අවසර ඉල්ලීමක් කරන නිසා, සැකසීම්වලට ඔබගේ ප්‍රතිචාරය සත්‍යාපනය කළ නොහැකිය."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> හට කොටස් <xliff:g id="APP_2">%2$s</xliff:g>ක් පෙන්වීමට ඉඩ දෙන්නද?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- එයට <xliff:g id="APP">%1$s</xliff:g> වෙතින් තොරතුරු කියවිය හැකිය"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"තාවකාලිකව සම්බන්ධ කළා"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"දුර්වල සම්බන්ධතාව"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"ජංගම දත්ත ස්වංක්‍රියව සම්බන්ධ නොවනු ඇත"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"සම්බන්ධතාවයක් නැත"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ලබා ගත හැකි වෙනත් ජාල නැත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0329914..51f0c7d 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasový asistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peňaženka"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skener QR kódov"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Odomknúť"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Zariadenie je uzamknuté"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenovanie tváre"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Odoslať"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Tvár sa nedá rozpoznať"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Používať radšej odtlačok"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth pripojené."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percento batérie nie je známe."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim v lietadle."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuté."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batéria <xliff:g id="NUMBER">%d</xliff:g> percent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Percentá batérie: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Na základe vášho používania zostáva <xliff:g id="TIME">%2$s</xliff:g>."</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Nabíja sa batéria, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Zobraziť všetky upozornenia"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Rozhranie TeleTypewriter je povolené."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibračné zvonenie."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Počas zdieľania, nahrávania alebo prenosu bude mať aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému obsahu, ktorý sa v nej bude zobrazovať alebo prehrávať. Preto venujte zvýšenú pozornosť heslám, platobným údajom, správam a ďalším citlivým údajom."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Pokračovať"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Aplikácia na zdieľanie alebo nahrávanie"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Chcete povoliť tejto aplikácii zdieľať alebo nahrávať?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Počas zdieľania, nahrávania alebo prenosu bude mať táto aplikácia prístup k všetkému na obrazovke, prípadne k obsahu, ktorý sa bude v zariadení prehrávať. Venujte preto zvýšenú pozornosť heslám, platobným údajom, správam a ďalším citlivým údajom."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Počas zdieľania, nahrávania alebo prenosu bude mať táto aplikácia prístup k všetkému obsahu, ktorý sa v nej bude zobrazovať alebo prehrávať. Venujte preto zvýšenú pozornosť heslám, platobným údajom, správam či ďalším citlivým údajom."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokované vaším správcom IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Snímanie obrazovky je zakázané pravidlami pre zariadenie"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Vymazať všetko"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovať"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"História"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odomknúť a použiť"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pri načítavaní kariet sa vyskytol problém. Skúste to neskôr."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavenia uzamknutej obrazovky"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skenovanie QR kódu"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Chcete vypnúť mobilné dáta?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nebudete mať prístup k dátam ani internetu prostredníctvom operátora <xliff:g id="CARRIER">%s</xliff:g>. Internet bude k dispozícii iba cez Wi‑Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"váš operátor"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Chcete prepnúť späť na operátora <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobilné dáta sa nebudú automaticky prepínať na základe dostupnosti"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nie, vďaka"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Áno, prepnúť"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Nastavenia nemôžu overiť vašu odpoveď, pretože určitá aplikácia blokuje žiadosť o povolenie."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Povoliť aplikácii <xliff:g id="APP_0">%1$s</xliff:g> zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Môže čítať informácie z aplikácie <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasne pripojené"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slabé pripojenie"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Automatické pripojenie cez mobilné dáta nefunguje"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bez pripojenia"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nie sú k dispozícii žiadne ďalšie siete"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b935de7..9e2a4bb 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovni pomočnik"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Google Denarnica"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Optični bralnik kod QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Odkleni"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Naprava je zaklenjena."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Optično branje obraza"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošlji"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Obraz ni bil prepoznan."</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Uporabite prstni odtis."</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Povezava Bluetooth vzpostavljena."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Neznan odstotek napolnjenosti baterije."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način za letalo."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Omrežje VPN je vklopljeno."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> odstotkov."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Napolnjenost baterije je <xliff:g id="PERCENTAGE">%1$s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterija se polni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> odstotkov."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Prikaži vsa obvestila"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter omogočen."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvonjenje z vibriranjem."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Pri deljenju, snemanju ali predvajanju aplikacije ima aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili ali drugimi občutljivimi podatki."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Naprej"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deljenje ali snemanje aplikacije"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Ali tej aplikaciji dovolite deljenje ali snemanje?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Pri deljenju, snemanju ali predvajanju ima ta aplikacija dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili ali drugimi občutljivimi podatki."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Pri deljenju, snemanju ali predvajanju aplikacije ima ta aplikacija dostop do vsega, kar je prikazano ali predvajano v tisti aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili ali drugimi občutljivimi podatki."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blokiral skrbnik za IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Zajemanje zaslonske slike je onemogočil pravilnik za naprave."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Izbriši vse"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljaj"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Zgodovina"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odklenite za uporabo"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavitve zaklepanja zaslona"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Optično branje kode QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Želite izklopiti prenos podatkov v mobilnih omrežjih?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Prek operaterja »<xliff:g id="CARRIER">%s</xliff:g>« ne boste imeli dostopa do podatkovne povezave ali interneta. Internet bo na voljo samo prek povezave Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"svojega operaterja"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Želite preklopiti nazaj na ponudnika <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Prenos podatkov v mobilnem omrežju ne preklopi samodejno glede na razpoložljivost."</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ne, hvala"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Da, preklopi"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Ker aplikacija zakriva zahtevo za dovoljenje, z nastavitvami ni mogoče preveriti vašega odziva."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Želite dovoliti, da aplikacija <xliff:g id="APP_0">%1$s</xliff:g> prikaže izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– lahko bere podatke v aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Začasno vzpostavljena povezava"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Slaba povezava"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna podatkovna povezava ne bo samodejna."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ni povezave"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nobeno drugo omrežje ni na voljo"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b7fef86..2547563 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portofoli"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Skaneri i kodeve QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Po skanon fytyrën"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Dërgo"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Fytyra nuk mund të njihet"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Përdor më mirë gjurmën e gishtit"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Pajisja është lidhur me \"bluetooth\"."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Përqindja e baterisë e panjohur."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"modaliteti i aeroplanit"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN-ja është aktive."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria ka edhe <xliff:g id="NUMBER">%d</xliff:g> për qind."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> përqind, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Bateria po karikohet, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Shiko të gjitha njoftimet"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletajpi është i aktivizuar."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zile me dridhje."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Gjatë shpërndarjes, regjistrimit ose transmetimit të një aplikacioni, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Vazhdo"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Shpërndaj ose regjistro një aplikacion"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Të lejohet që ky aplikacion të shpërndajë ose të regjistrojë?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Gjatë shpërndarjes, regjistrimit ose transmetimit, ky aplikacion ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacionet e tjera të ndjeshme."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Gjatë shpërndarjes, regjistrimit ose transmetimit, ky aplikacioni ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacionet e tjera të ndjeshme."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"U bllokua nga administratori yt i teknologjisë së informacionit"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Regjistrimi i ekranit është çaktivizuar nga politika e pajisjes."</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Pastroji të gjitha"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Menaxho"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historiku"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Shkyçe për ta përdorur"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cilësimet e ekranit të kyçjes"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skano kodin QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profili i punës"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modaliteti i aeroplanit"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Të çaktivizohen të dhënat celulare?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nuk do të kesh qasje te të dhënat ose interneti nëpërmjet <xliff:g id="CARRIER">%s</xliff:g>. Interneti do të ofrohet vetëm nëpërmjet Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operatori yt celular"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Të kalohet përsëri te <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Të dhënat celulare nuk do të ndërrohen automatikisht në bazë të disponueshmërisë"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Jo, faleminderit"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Po, ndërro"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Duke qenë se një aplikacion po bllokon një kërkesë për leje, \"Cilësimet\" nuk mund të verifikojnë përgjigjen tënde."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Të lejohet <xliff:g id="APP_0">%1$s</xliff:g> që të shfaqë pjesë të <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Mund të lexojë informacion nga <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Lidhur përkohësisht"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Lidhje e dobët"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Të dhënat celulare nuk do të lidhen automatikisht"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nuk ka lidhje"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nuk ofrohet asnjë rrjet tjetër"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 56cb3c8..fb17123 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помоћ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Новчаник"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Скенер QR кода"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Откључајте"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Уређај је закључан"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лица"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Пошаљи"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Лице није препознато"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користите отисак прста"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth је прикључен."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Проценат напуњености батерије није познат."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим рада у авиону."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN је укључен."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија је на <xliff:g id="NUMBER">%d</xliff:g> посто."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија је на <xliff:g id="PERCENTAGE">%1$s</xliff:g> посто, преостало време на основу коришћења је <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Батерија се пуни, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> посто."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Погледајте сва обавештења"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter је омогућен."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Вибрација звона."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Када делите, снимате или пребацујете апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Будите пажљиви са лозинкама, информацијама о плаћању, порукама или другим осетљивим информацијама."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Настави"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Делите или снимите апликацију"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Желите да дозволите овој апликацији да дели или снима?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Када делите, снимате или пребацујете, ова апликација има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Будите пажљиви са лозинкама, информацијама о плаћању, порукама или другим осетљивим информацијама."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Када делите, снимате или пребацујете апликацију, ова апликација има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Будите пажљиви са лозинкама, информацијама о плаћању, порукама или другим осетљивим информацијама."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Блокира ИТ администратор"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Снимање екрана је онемогућено смерницама за уређај"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Обриши све"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управљајте"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Историја"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Откључај ради коришћења"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Дошло је до проблема при преузимању картица. Пробајте поново касније"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Подешавања закључаног екрана"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Скенирајте QR кôд"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Желите да искључите мобилне податке?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Нећете имати приступ подацима или интернету преко мобилног оператера <xliff:g id="CARRIER">%s</xliff:g>. Интернет ће бити доступан само преко WiFi везе."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"мобилни оператер"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Желите да се вратите на мобилног оператера <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Мобилни подаци се неће аутоматски променити на основу доступности"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Не, хвала"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Да, пређи"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Подешавања не могу да верификују ваш одговор јер апликација скрива захтев за дозволу."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Желите ли да дозволите апликацији <xliff:g id="APP_0">%1$s</xliff:g> да приказује исечке из апликације <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Може да чита податке из апликације <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено повезано"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Веза је лоша"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Није успело аутом. повезивање преко моб. података"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Веза није успостављена"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Није доступна ниједна друга мрежа"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 8de8d09..6e74ea2 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Röstassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-skanner"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås upp"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten är låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Registrerar ansikte"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Skicka"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansiktet kändes inte igen"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Använd fingeravtryck"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ansluten."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Okänd batterinivå."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flygplansläge"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN har aktiverats."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteri: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batteriet laddas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Visa alla aviseringar"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter aktiverad."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibrerande ringsignal."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"När du delar, spelar in eller castar en app har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas eller spelas upp i appen. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Fortsätt"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dela eller spela in en app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vill du tillåta att den här appen delar eller spelar in?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"När du delar, spelar in eller castar har den här appen åtkomst till allt som visas på skärmen eller spelas upp på enheten. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"När du delar, spelar in eller castar en app har den här appen åtkomst till allt som visas eller spelas upp i appen. Så var försiktig med lösenord, betalningsuppgifter, meddelanden och andra känsliga uppgifter."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Blockeras av IT-administratören"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Skärminspelning är inaktiverat av enhetspolicyn"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Rensa alla"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Hantera"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås upp för att använda"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Det gick inte att hämta dina kort. Försök igen senare."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Inställningar för låsskärm"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skanna QR-kod"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vill du inaktivera mobildata?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Du kan inte skicka data eller använda internet via <xliff:g id="CARRIER">%s</xliff:g>. Internetanslutning blir bara möjlig via wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"din operatör"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Vill du byta tillbaka till <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobildatakällan byts inte automatiskt efter tillgänglighet"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Nej tack"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ja, byt"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Svaret kan inte verifieras av Inställningar eftersom en app skymmer en begäran om behörighet."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Tillåter du att bitar av <xliff:g id="APP_2">%2$s</xliff:g> visas i <xliff:g id="APP_0">%1$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– Kan läsa information från <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tillfälligt ansluten"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Dålig anslutning"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Du ansluts inte till mobildata automatiskt"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen anslutning"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Inga andra nätverk är tillgängliga"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index cfa370e..e8a7caf 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Mapendekezo ya Sauti"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Pochi"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Kichanganuzi cha Msimbo wa QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Fungua"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Kifaa kimefungwa"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Inachanganua uso"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Tuma"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Imeshindwa kutambua uso"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Badala yake, tumia alama ya kidole"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth imeunganishwa."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Asilimia ya betri haijulikani."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hali ya ndegeni."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN imewashwa."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Asilimia <xliff:g id="NUMBER">%d</xliff:g> ya betri"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Betri ina asilimia <xliff:g id="PERCENTAGE">%1$s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%2$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Betri inachaji, asilimia <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Angalia arifa zote"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Kichapishaji cha Tele kimewezeshwa."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Mtetemo wa mlio"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Unapotuma, kurekodi au kushiriki programu, programu ya <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Hivyo kuwa mwangalifu na manenosiri, maelezo ya malipo, ujumbe au maelezo mengine nyeti."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Endelea"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Shiriki au rekodi programu"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Ungependa kuruhusu programu hii ishiriki au irekodi?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Unapotuma, kurekodi au kushiriki, programu hii inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Hivyo kuwa mwangalifu na manenosiri, maelezo ya malipo, ujumbe au maelezo mengine nyeti."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Unapotuma, kurekodi au kushiriki programu, programu hii inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Hivyo kuwa mwangalifu na manenosiri, maelezo ya malipo, ujumbe au maelezo mengine nyeti."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Umezuiwa na msimamizi wako wa TEHAMA"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Mchakato wa kurekodi skrini umezimwa na sera ya kifaa"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Futa zote"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Dhibiti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Changanua msimbo wa QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Hutasikia kengele yako inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Ungependa kuzima data ya mtandao wa simu?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Hutaweza kufikia data au intaneti kupitia <xliff:g id="CARRIER">%s</xliff:g>. Intaneti itapatikana kupitia Wi-Fi pekee."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"mtoa huduma wako"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Ungependa kubadilisha ili utumie data ya mtandao wa <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Data ya mtandao wa simu haitabadilika kiotomatiki kulingana na upatikanaji"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Hapana"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ndiyo, badili"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Kwa sababu programu nyingine inazuia ombi la ruhusa, hatuwezi kuthibitisha jibu lako katika Mipangilio."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Ungependa kuruhusu <xliff:g id="APP_0">%1$s</xliff:g> ionyeshe vipengee <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Inaweza kusoma maelezo kutoka <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Imeunganishwa kwa muda"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Muunganisho duni"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data ya mtandao wa simu haitaunganishwa kiotomatiki"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Hakuna muunganisho"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Hakuna mitandao mingine inayopatikana"</string>
diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
index d9df337..707bc9e 100644
--- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
@@ -17,7 +17,6 @@
 <resources>
     <dimen name="notification_panel_margin_horizontal">48dp</dimen>
     <dimen name="status_view_margin_horizontal">62dp</dimen>
-    <dimen name="bouncer_user_switcher_y_trans">20dp</dimen>
 
     <!-- qs_tiles_page_horizontal_margin should be margin / 2, otherwise full space between two
          pages is margin * 2, and that makes tiles page not appear immediately after user swipes to
diff --git a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
index 97ead01..b98165f 100644
--- a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
@@ -21,4 +21,6 @@
     <!-- Space between status view and notification shelf -->
     <dimen name="keyguard_status_view_bottom_margin">70dp</dimen>
     <dimen name="keyguard_clock_top_margin">80dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">186dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">110dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 17f82b5..8b41a44 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -21,7 +21,6 @@
      for different hardware and product builds. -->
 <resources>
     <dimen name="status_view_margin_horizontal">124dp</dimen>
-    <dimen name="bouncer_user_switcher_y_trans">200dp</dimen>
 
     <dimen name="large_screen_shade_header_left_padding">24dp</dimen>
     <dimen name="qqs_layout_padding_bottom">40dp</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index caea7a0..41e1f3f 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"குரல் உதவி"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR குறியீடு ஸ்கேனர்"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"அன்லாக் செய்"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"சாதனம் பூட்டப்பட்டுள்ளது"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"முகத்தை ஸ்கேன் செய்கிறது"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"அனுப்பு"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"முகத்தை கண்டறிய இயலவில்லை"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"கைரேகையை உபயோகிக்கவும்"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"புளூடூத் இணைக்கப்பட்டது."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"பேட்டரி சதவீதம் தெரியவில்லை."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"விமானப் பயன்முறை."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN இயக்கத்தில் உள்ளது."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"பேட்டரி சக்தி <xliff:g id="NUMBER">%d</xliff:g> சதவிகிதம் உள்ளது."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"பேட்டரி: <xliff:g id="PERCENTAGE">%1$s</xliff:g> சதவீதம், உபயோகத்தின் அடிப்படையில் <xliff:g id="TIME">%2$s</xliff:g> மீதமுள்ளது"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"பேட்டரி சார்ஜ் ஆகிறது, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> சதவீதம் உள்ளது."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"எல்லா அறிவிப்புகளையும் காட்டும்"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter இயக்கப்பட்டது."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"ரிங்கர் அதிர்வு."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"ஓர் ஆப்ஸை நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அந்த ஆப்ஸில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், பிற பாதுகாக்கப்பட வேண்டிய தகவல்கள் ஆகியவை குறித்து கவனத்துடன் இருங்கள்."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"தொடர்க"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ஆப்ஸைப் பகிர்தல் அல்லது ரெக்கார்டு செய்தல்"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"பகிர்வதற்கோ ரெக்கார்டு செய்வதற்கோ இந்த ஆப்ஸை அனுமதிக்கவா?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ திரையில் காட்டப்படும்/சாதனத்தில் பிளே செய்யப்படும் அனைத்தையும் இந்த ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள் அல்லது பாதுகாக்கப்பட வேண்டிய பிற தகவல்கள் குறித்துக் கவனமாக இருங்கள்."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"ஓர் ஆப்ஸை நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அதில் காட்டப்படும்/பிளே செய்யப்படும் அனைத்தையும் இந்த ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள் அல்லது பாதுகாக்கப்பட வேண்டிய பிற தகவல்கள் குறித்துக் கவனமாக இருங்கள்."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"உங்கள் IT நிர்வாகி தடுத்துள்ளார்"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"\'திரையைப் படமெடுத்தல்\' சாதனக் கொள்கையின்படி முடக்கப்பட்டுள்ளது"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"எல்லாவற்றையும் அழி"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"நிர்வகி"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"இதுவரை வந்த அறிவிப்புகள்"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"பயன்படுத்துவதற்கு அன்லாக் செய்க"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"பூட்டுத் திரை அமைப்புகள்"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR குறியீட்டை ஸ்கேன் செய்தல்"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"அடுத்த அலாரத்தை <xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு கேட்க மாட்டீர்கள்"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"மொபைல் டேட்டாவை ஆஃப் செய்யவா?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> மூலம் டேட்டா அல்லது இணையத்தை உங்களால் பயன்படுத்த முடியாது. வைஃபை வழியாக மட்டுமே இணையத்தைப் பயன்படுத்த முடியும்."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"உங்கள் மொபைல் நிறுவனம்"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g>க்கு மறுபடியும் மாற்றவா?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"கிடைக்கும் நிலையின் அடிப்படையில் மொபைல் டேட்டா தானாகவே மாறாது"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"வேண்டாம்"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"மாற்று"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"அனுமதிக் கோரிக்கையை ஆப்ஸ் மறைப்பதால், அமைப்புகளால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> ஆப்ஸை, <xliff:g id="APP_2">%2$s</xliff:g> ஆப்ஸின் விழிப்பூட்டல்களைக் காண்பிக்க அனுமதிக்கவா?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- இது, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டிலிருந்து தகவலைப் படிக்கும்"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"தற்காலிகமாக இணைக்கப்பட்டுள்ளது"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"இணைப்பு மோசமாக உள்ளது"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"மொபைல் டேட்டாவுடன் தானாக இணைக்காது"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"இணைப்பு இல்லை"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"வேறு நெட்வொர்க்குகள் எதுவும் கிடைக்கவில்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 22d7190..9ad0277c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR కోడ్ స్కానర్"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"అన్‌లాక్ చేయి"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ముఖాన్ని స్కాన్ చేస్తోంది"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"పంపు"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ముఖం గుర్తించడం కుదరలేదు"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"బదులుగా వేలిముద్రను ఉపయోగించండి"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"బ్యాటరీ శాతం తెలియదు."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ఎయిర్‌ప్లేన్ మోడ్."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPNలో."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"బ్యాటరీ <xliff:g id="NUMBER">%d</xliff:g> శాతం."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"బ్యాటరీ <xliff:g id="PERCENTAGE">%1$s</xliff:g> శాతం ఉంది, మీ వినియోగాన్ని బట్టి <xliff:g id="TIME">%2$s</xliff:g> పని చేస్తుంది"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"బ్యాటరీ ఛార్జ్ అవుతోంది, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> శాతం వద్ద ఉంది."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"అన్ని నోటిఫికేషన్‌లను చూడండి"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"టెలిటైప్‌రైటర్ ప్రారంభించబడింది."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"రింగర్ వైబ్రేట్‌లో ఉంది."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"మీరు ఏదైనా యాప్‌ను షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఆ యాప్‌లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌కు యాక్సెస్ ఉంటుంది. కాబట్టి, పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, లేదా ఏదైనా ఇతర సున్నితమైన సమాచారం పట్ల జాగ్రత్త వహించండి."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"కొనసాగించండి"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"యాప్‌ను షేర్ చేయండి లేదా రికార్డ్ చేయండి"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"షేర్ చేయడానికి లేదా రికార్డ్ చేయడానికి ఈ యాప్‌ను అనుమతించాలా?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"మీరు షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఈ యాప్ మీ స్క్రీన్‌పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా యాక్సెస్‌ను కలిగి ఉంటుంది. కాబట్టి, పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, లేదా ఏదైనా ఇతర సున్నితమైన సమాచారం పట్ల జాగ్రత్త వహించండి."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"మీరు ఏదైనా యాప్‌ను షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఆ యాప్‌లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా ఈ యాప్ యాక్సెస్‌ను కలిగి ఉంటుంది. కాబట్టి, పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, లేదా ఏదైనా ఇతర సున్నితమైన సమాచారం పట్ల జాగ్రత్త వహించండి."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"మీ IT అడ్మిన్ ద్వారా బ్లాక్ చేయబడింది"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"పరికర పాలసీ ద్వారా స్క్రీన్ క్యాప్చర్ చేయడం డిజేబుల్ చేయబడింది"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"అన్నీ క్లియర్ చేయండి"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"మేనేజ్ చేయండి"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"హిస్టరీ"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ఉపయోగించడానికి అన్‌లాక్ చేయండి"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"మీ కార్డ్‌లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"లాక్ స్క్రీన్ సెట్టింగ్‌లు"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR కోడ్‌ను స్కాన్ చేయండి"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"మొబైల్ డేటాను ఆఫ్ చేయాలా?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"\"<xliff:g id="CARRIER">%s</xliff:g>\" ద్వారా మీకు డేటా లేదా ఇంటర్నెట్‌కు యాక్సెస్ ఉండదు. Wi-Fi ద్వారా మాత్రమే ఇంటర్నెట్ అందుబాటులో ఉంటుంది."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"మీ క్యారియర్"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g>కి తిరిగి మారాలా?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"మొబైల్ డేటా లభ్యత ఆధారంగా ఆటోమేటిక్‌గా స్విచ్ అవ్వదు"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"వద్దు, థ్యాంక్స్"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"అవును, మార్చండి"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"అనుమతి రిక్వెస్ట్‌కు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్‌లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> స్లైస్‌లను చూపించడానికి <xliff:g id="APP_0">%1$s</xliff:g>ని అనుమతించండి?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- ఇది <xliff:g id="APP">%1$s</xliff:g> నుండి సమాచారాన్ని చదువుతుంది"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"తాత్కాలికంగా కనెక్ట్ చేయబడింది"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"కనెక్షన్ బాగాలేదు"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"మొబైల్ డేటా ఆటోమెటిక్‌గా కనెక్ట్ అవ్వదు"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"కనెక్షన్ లేదు"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ఇతర నెట్‌వర్క్‌లేవీ అందుబాటులో లేవు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index bb3e4fa..f4116ad 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -125,7 +125,7 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ตัวช่วยเสียง"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"เครื่องมือสแกนคิวอาร์โค้ด"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"ปลดล็อก"</string>
+    <string name="accessibility_unlock_button" msgid="3613812140816244310">"ปลดล็อกแล้ว"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"อุปกรณ์ถูกล็อก"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"กำลังสแกนใบหน้า"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ส่ง"</string>
@@ -168,7 +168,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"ไม่รู้จักใบหน้า"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ใช้ลายนิ้วมือแทน"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"เชื่อมต่อบลูทูธแล้ว"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ไม่ทราบเปอร์เซ็นต์แบตเตอรี่"</string>
@@ -180,8 +180,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"โหมดบนเครื่องบิน"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN เปิดอยู่"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"แบตเตอรี่ <xliff:g id="NUMBER">%d</xliff:g> เปอร์เซ็นต์"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"แบตเตอรี่ <xliff:g id="PERCENTAGE">%1$s</xliff:g> เปอร์เซ็นต์ ใช้ได้อีกประมาณ <xliff:g id="TIME">%2$s</xliff:g> ทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"กำลังชาร์จแบตเตอรี่ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> เปอร์เซ็นต์"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"ดูการแจ้งเตือนทั้งหมด"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"เปิดใช้งาน TeleTypewriter อยู่"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"เสียงเรียกเข้าแบบสั่น"</string>
@@ -375,16 +380,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"เมื่อกำลังแชร์ บันทึก หรือแคสต์แอป \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังเกี่ยวกับรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ หรือข้อมูลที่ละเอียดอ่อนอื่นๆ"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"ต่อไป"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"แชร์หรือบันทึกแอป"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"อนุญาตให้แอปนี้แชร์หรือบันทึกไหม"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"เมื่อกำลังแชร์ บันทึก หรือแคสต์ แอปนี้จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังเกี่ยวกับรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ หรือข้อมูลที่ละเอียดอ่อนอื่นๆ"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"เมื่อกำลังแชร์ บันทึก หรือแคสต์แอป แอปนี้จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังเกี่ยวกับรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ หรือข้อมูลที่ละเอียดอ่อนอื่นๆ"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ผู้ดูแลระบบไอทีบล็อกไว้"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"การจับภาพหน้าจอปิดใช้โดยนโยบายด้านอุปกรณ์"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ล้างทั้งหมด"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"จัดการ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ประวัติ"</string>
@@ -500,7 +500,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"สแกนคิวอาร์โค้ด"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"เครื่องมือสแกนคิวอาร์โค้ด"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +739,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ปิดอินเทอร์เน็ตมือถือไหม"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"คุณจะใช้เน็ตมือถือหรืออินเทอร์เน็ตผ่าน \"<xliff:g id="CARRIER">%s</xliff:g>\" ไม่ได้ แต่จะใช้ผ่าน Wi-Fi ได้เท่านั้น"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ผู้ให้บริการของคุณ"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"เปลี่ยนกลับเป็น <xliff:g id="CARRIER">%s</xliff:g> หรือไม่"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"อินเทอร์เน็ตมือถือไม่ได้เปลี่ยนตามความพร้อมบริการโดยอัตโนมัติ"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"ไม่เป็นไร"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ใช่ เปลี่ยนเลย"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"เนื่องจากแอปหนึ่งได้บดบังคำขอสิทธิ์ ระบบจึงไม่สามารถยืนยันคำตอบของคุณสำหรับการตั้งค่าได้"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"อนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> แสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- อ่านข้อมูลจาก <xliff:g id="APP">%1$s</xliff:g> ได้"</string>
@@ -929,6 +933,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"เชื่อมต่อแล้วชั่วคราว"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"การเชื่อมต่อไม่ดี"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"อินเทอร์เน็ตมือถือจะไม่เชื่อมต่ออัตโนมัติ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ไม่มีการเชื่อมต่อ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ไม่มีเครือข่ายอื่นๆ ที่พร้อมใช้งาน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 8ddb64e..468c8a4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Scanner ng QR Code"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"I-unlock"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Naka-lock ang device"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sina-scan ang mukha"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Ipadala"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Hindi makilala ang mukha"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gumamit ng fingerprint"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Nakakonekta ang Bluetooth."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Hindi alam ang porsyento ng baterya."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode na eroplano."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Naka-on ang VPN."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Baterya <xliff:g id="NUMBER">%d</xliff:g> (na) porsyento."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (na) porsyento ang baterya, nasa <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa paggamit mo"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Nagcha-charge ang baterya, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> (na) porsyento."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Tingnan ang lahat ng notification"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Pinapagana ang TeleTypewriter."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Pag-vibrate ng ringer."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kapag nagbabahagi, nagre-record, o nagka-cast ka ng app, may access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga password, detalye ng pagbabayad, mensahe, o iba pang impormasyon."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Magpatuloy"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Ibahagi o i-record ang isang app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Payagan ang app na ito na magbahagi o mag-record?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kapag nagbabahagi, nagre-record, o nagka-cast ka, may access ang app na ito sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga password, detalye ng pagbabayad, mensahe, o iba pang sensitibong impormasyon."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kapag nagbabahagi, nagre-record, o nagka-cast ka ng app, may access ang app na ito sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga password, detalye ng pagbabayad, mensahe, o iba pang impormasyon."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Na-block ng iyong IT admin"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Naka-disable ang pag-screen capture ayon sa patakaran ng device"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"I-clear lahat"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pamahalaan"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"I-unlock para magamit"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mga setting ng lock screen"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"I-scan ang QR code"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Scanner ng QR code"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Hindi mo maririnig ang iyong susunod na alarm ng <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"I-off ang mobile data?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Hindi ka magkaka-access sa data o internet sa pamamagitan ng <xliff:g id="CARRIER">%s</xliff:g>. Available lang ang internet sa pamamagitan ng Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ang iyong carrier"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Bumalik sa <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Hindi awtomatikong magbabago ang mobile data base sa availability"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Hindi, salamat na lang"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Oo, lumipat"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Hindi ma-verify ng Mga Setting ang iyong tugon dahil may app na tumatakip sa isang kahilingan sa pagpapahintulot."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Payagan ang <xliff:g id="APP_0">%1$s</xliff:g> na ipakita ang mga slice ng <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Nakakabasa ito ng impormasyon mula sa <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Pansamantalang nakakonekta"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Mahina ang koneksyon"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Hindi awtomatikong kokonekta ang mobile data"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Walang koneksyon"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Walang available na iba pang network"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 177ce98..7c126e5 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sesli Yardım"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cüzdan"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodu tarayıcı"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Kilidi aç"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilitlendi"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yüz taranıyor"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Gönder"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Yüz tanınamadı"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bunun yerine parmak izi kullanın"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth bağlandı."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pil yüzdesi bilinmiyor."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçak modu."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN açık."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Pil yüzdesi: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pil yüzde <xliff:g id="PERCENTAGE">%1$s</xliff:g> dolu. Kullanımınıza göre yaklaşık <xliff:g id="TIME">%2$s</xliff:g> süresi kaldı"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Pil şarj oluyor, yüzde <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Tüm bildirimleri göster"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter etkin."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Telefon zili titreşim."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Bir uygulamayı paylaşma, kaydetme ve yayınlama özelliklerini kullandığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Devam"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Uygulamayı paylaşın veya kaydedin"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Bu uygulamanın paylaşım ve kayıt yapmasına izin verilsin mi?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Paylaşım, kayıt ve yayınlama özelliklerini kullandığınızda, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Bir uygulamayı paylaşma, kaydetme ve yayınlama özelliklerini kullandığınızda , söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Dolayısıyla şifreler, ödeme ayrıntıları, mesajlar veya diğer hassas bilgiler konusunda dikkatli olun."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"BT yöneticiniz tarafından engellendi"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ekran görüntüsü alma, cihaz politikası tarafından devre dışı bırakıldı"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tümünü temizle"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Yönet"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geçmiş"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Kullanmak için kilidi aç"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilit ekranı ayarları"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR kodunu tara"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobil veri kapatılsın mı?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> üzerinden veri veya internet erişiminiz olmayacak. İnternet yalnızca kablosuz bağlantı üzerinden kullanılabilecek."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operatörünüz"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> operatörüne geri dönülsün mü?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Uygunluk durumuna göre otomatik olarak mobil veriye geçilmez"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Hayır, teşekkürler"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Evet, geçilsin"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Bir uygulama bir izin isteğinin anlaşılmasını engellediğinden, Ayarlar, yanıtınızı doğrulayamıyor."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> uygulamasının, <xliff:g id="APP_2">%2$s</xliff:g> dilimlerini göstermesine izin verilsin mi?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> uygulamasından bilgileri okuyabilir"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Geçici olarak bağlandı"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Bağlantı zayıf"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil veri otomatik olarak bağlanmıyor"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yok"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Kullanılabilir başka ağ yok"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index fdfcadc..1c32bb1d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Голосові підказки"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Гаманець"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Сканер QR-коду"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Розблокувати"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Пристрій заблоковано"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканування обличчя"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Надіслати"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Обличчя не розпізнано"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скористайтеся відбитком"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth під’єднано."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Відсоток заряду акумулятора невідомий."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим польоту."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"Мережу VPN увімкнено."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд акумулятора у відсотках: <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Згідно з даними про використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> заряду акумулятора – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Акумулятор заряджається, поточний заряд <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> відсотків."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Переглянути всі сповіщення"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Телетайп увімкнено."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Дзвінок на вібросигналі."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Коли ви показуєте, записуєте або транслюєте додаток, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається або відтворюється в цьому додатку. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Продовжити"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Показувати або записувати додаток"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Дозволити цьому додатку показувати або записувати екран?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Коли ви показуєте, записуєте або транслюєте екран, цей додаток отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Коли ви показуєте, записуєте або транслюєте додаток, доступ до всього, що відображається або відтворюється в ньому, отримує цей додаток. Тому будьте уважні з паролями, повідомленнями, платіжною й іншою конфіденційною інформацією."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Заблоковано адміністратором"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Запис екрана вимкнено згідно з правилами для пристрою"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Очистити все"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Керувати"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Історія"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Сканувати QR-код"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Наступний сигнал о <xliff:g id="WHEN">%1$s</xliff:g> не пролунає"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Вимкнути мобільний Інтернет?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Ви не матимете доступу до даних чи Інтернету через оператора <xliff:g id="CARRIER">%s</xliff:g>. Інтернет буде доступний лише через Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ваш оператор"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Перейти на <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Пристрій не перемикатиметься на мобільний Інтернет автоматично"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Ні, дякую"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Так, перемикатися"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Не вдається підтвердити вашу відповідь у налаштуваннях, оскільки інший додаток заступає запит на дозвіл."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Дозволити додатку <xliff:g id="APP_0">%1$s</xliff:g> показувати фрагменти додатка <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Має доступ до інформації з додатка <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Тимчасово з’єднано"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Погане з’єднання"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобільний Інтернет не підключатиметься автоматично"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Немає з\'єднання"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Інші мережі недоступні"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e222148..b78c50e 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"والٹ"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"‏QR کوڈ اسکینر"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"اسکیننگ چہرہ"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"بھیجیں"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"چہرے کی پہچان نہیں ہو سکی"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"اس کے بجائے فنگر پرنٹ استعمال کریں"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوٹوتھ مربوط ہے۔"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"بیٹری کی فیصد نامعلوم ہے۔"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"ہوائی جہاز وضع۔"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"‏VPN آن ہے۔"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"بیٹری <xliff:g id="NUMBER">%d</xliff:g> فیصد۔"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"آپ کے استعمال کی بنیاد پر بیٹری <xliff:g id="PERCENTAGE">%1$s</xliff:g> فیصد، تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"بیٹری چارج ہو رہی ہے، اس وقت <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> فیصد ہے۔"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"تمام اطلاعات دیکھیں"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"ٹیلی ٹائپ رائٹر فعال ہے۔"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"رنگر وائبریٹ۔"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو آپ کی اسکرین پر دکھائی گئی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"جاری رکھیں"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ایپ کا اشتراک یا ریکارڈ کریں"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"اس ایپ کو اشتراک یا ریکارڈ کرنے کی اجازت دیں؟"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو اس ایپ کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلنے والی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو اس ایپ کو آپ کی اسکرین پر دکھائی گئی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ اس لیے پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، یا دیگر حساس معلومات کے سلسلے میں محتاط رہیں۔"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"‏آپ کے IT منتظم نے مسدود کر دیا"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"اسکرین کو کیپچر کرنا آلہ کی پالیسی کے ذریعے غیر فعال ہے"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"سبھی کو صاف کریں"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"نظم کریں"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سرگزشت"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"استعمال کرنے کے لیے غیر مقفل کریں"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"مقفل اسکرین کی ترتیبات"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"‏QR کوڈ اسکین کریں"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"موبائل ڈیٹا آف کریں؟"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"‏آپ کو <xliff:g id="CARRIER">%s</xliff:g> کے ذریعے ڈیٹا یا انٹرنیٹ تک رسائی حاصل نہیں ہوگی۔ انٹرنیٹ صرف Wi-Fi کے ذریعے دستیاب ہوگا۔"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"آپ کا کریئر"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> پر واپس سوئچ کریں؟"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"دستیابی کی بنیاد پر موبائل ڈیٹا خودکار طور پر تبدیل نہیں ہوگا"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"نہیں شکریہ"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"ہاں، سوئچ کریں"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"چونکہ ایک ایپ اجازت کی درخواست کو مبہم کر رہی ہے، لہذا ترتیبات آپ کے جواب کی توثیق نہیں کر سکتی ہیں۔"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> کو <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانے کی اجازت دیں؟"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- یہ <xliff:g id="APP">%1$s</xliff:g> کی معلومات پڑھ سکتا ہے"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"عارضی طور پر منسلک ہے"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"کمزور کنکشن"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"موبائل ڈیٹا خودکار طور پر منسلک نہیں ہوگا"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"کوئی کنکشن نہیں"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"کوئی دوسرا نیٹ ورک دستیاب نہیں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 597fa4e..3b34ac5 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ovozli yordam"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kod skaneri"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Qulfdan chiqarish"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Qurilma qulflandi"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yuzni skanerlash"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Yuborish"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Yuz aniqlanmadi"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmoq izi orqali urining"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ulandi."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareya quvvati foizi nomaʼlum."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Parvoz rejimi"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN yoniq."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> foiz."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya quvvati <xliff:g id="PERCENTAGE">%1$s</xliff:g> foiz, joriy holatda yana <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batareya quvvat olmoqda, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> foiz."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Barcha bildirishnomalarni ko‘rish"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter yoqildi."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibratsiyali qo‘ng‘iroq"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Ulashish, yozib olish va translatsiya qilish vaqtida <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar yoki boshqa maxfiy axborot chiqmasligi uchun ehtiyot boʻling."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Davom etish"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Ilovada ulashish yoki yozib olish"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Bu ilovaga ulashish yoki yozib olish uchun ruxsat berilsinmi?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Ulashish, yozib olish va translatsiya qilish vaqtida bu ilova ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar yoki boshqa maxfiy axborot chiqmasligi uchun ehtiyot boʻling."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Ulashish, yozib olish va translatsiya qilish vaqtida bu ilova ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar yoki boshqa maxfiy axborot chiqmasligi uchun ehtiyot boʻling."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"AT administratoringiz tomonidan bloklangan"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ekranni tasvirga olish qurilmadan foydalanish tartibi tomonidan faolsizlantirilgan"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hammasini tozalash"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Boshqarish"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Tarix"</string>
@@ -500,7 +501,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Foydalanish uchun qulfdan chiqarish"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Bildirgilarni yuklashda xatolik yuz berdi, keyinroq qaytadan urining"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Qulflangan ekran sozlamalari"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"QR kodni skanerlash"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR kod skaneri"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
@@ -739,6 +740,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobil internet uzilsinmi?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> orqali internetdan foydalana olmaysiz. Internet faqat Wi-Fi orqali ishlaydi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"aloqa operatoringiz"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"<xliff:g id="CARRIER">%s</xliff:g> xizmati qaytarilsinmi?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Mobil internet mavjudligi asosida avtomatik almashtirilmaydi"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Kerak emas"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ha, almashtirilsin"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Ilova ruxsatnoma so‘roviga xalaqit qilayotgani tufayli, “Sozlamalar” ilovasi javobingizni tekshira olmaydi."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> ilovasiga <xliff:g id="APP_2">%2$s</xliff:g> ilovasidan fragmentlar ko‘rsatishga ruxsat berilsinmi?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"– <xliff:g id="APP">%1$s</xliff:g> ma’lumotlarini o‘qiy oladi"</string>
@@ -929,6 +934,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ulandi"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vaqtincha ulangan"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Aloqa beqaror"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil internetga avtomatik ulanmaydi"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Internetga ulanmagansiz"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Boshqa tarmoqlar mavjud emas"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 485676a..ea86c1e 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Trợ lý thoại"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Ví"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Trình quét mã QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Mở khóa"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Đã khóa thiết bị"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Quét tìm khuôn mặt"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Gửi"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Không nhận ra khuôn mặt"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Hãy dùng vân tay"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Đã kết nối bluetooth."</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Tỷ lệ phần trăm pin không xác định."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Chế độ trên máy bay."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN đang bật."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> phần trăm pin."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> phần trăm pin, còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Đang sạc pin, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Xem tất cả thông báo"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Đã bật TeleTypewriter."</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Chuông rung."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Khi bạn chia sẻ, ghi hoặc truyền ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ mật khẩu, thông tin thanh toán, tin nhắn hoặc thông tin nhạy cảm khác."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Tiếp tục"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Chia sẻ hoặc ghi ứng dụng"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Cho phép ứng dụng này chia sẻ hoặc ghi?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Khi bạn chia sẻ, ghi hoặc truyền, ứng dụng này sẽ truy cập được vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy để ý đến mật khẩu, thông tin thanh toán, tin nhắn hoặc thông tin nhạy cảm khác."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Khi bạn chia sẻ, ghi hoặc truyền ứng dụng, ứng dụng này sẽ truy cập được vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy để ý đến mật khẩu, thông tin thanh toán, tin nhắn hoặc thông tin nhạy cảm khác."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Bị quản trị viên CNTT chặn"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Tính năng chụp ảnh màn hình đã bị tắt theo chính sách thiết bị"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Xóa tất cả"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Quản lý"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Lịch sử"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Mở khóa để sử dụng"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cài đặt màn hình khóa"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Quét mã QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Tắt dữ liệu di động?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Bạn sẽ không có quyền sử dụng dữ liệu hoặc truy cập Internet thông qua chế độ <xliff:g id="CARRIER">%s</xliff:g>. Bạn chỉ có thể truy cập Internet thông qua Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"nhà mạng của bạn"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Chuyển về <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Dữ liệu di động sẽ không tự động chuyển dựa trên tình trạng phủ sóng"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Không, cảm ơn"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Có, hãy chuyển"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Vì ứng dụng đang che khuất yêu cầu cấp quyền nên Cài đặt không thể xác minh câu trả lời của bạn."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Cho phép <xliff:g id="APP_0">%1$s</xliff:g> hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Có thể đọc thông tin từ <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tạm thời có kết nối"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Kết nối kém"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Dữ liệu di động sẽ không tự động kết nối"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Không có kết nối mạng"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Không có mạng nào khác"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 1b65855..ffe4f5f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"钱包"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"二维码扫描器"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"正在扫描面孔"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"发送"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"人脸识别失败"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"改用指纹"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"蓝牙已连接。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"电池电量百分比未知。"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飞行模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已开启。"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"电池电量为百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"电池电量为 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,根据您的使用情况,大约还可使用<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"正在充电,已完成 <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%。"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"查看所有通知"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"电传打字机已启用。"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"振铃器振动。"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"在您进行分享、录制或投射时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问通过此应用显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"继续"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或录制应用"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"是否允许此应用进行分享或录制?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"在您进行分享、录制或投屏时,此应用可以访问您的屏幕显示或设备播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"在您进行分享、录制或投屏时,此应用可以访问通过此应用显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"已被 IT 管理员禁止"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"设备政策已停用屏幕截图功能"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"历史记录"</string>
@@ -499,8 +500,9 @@
     <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"正在更新"</string>
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解锁设备即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"获取您的卡片时出现问题,请稍后重试"</string>
-    <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁定屏幕设置"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"扫描二维码"</string>
+    <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁屏设置"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"您在<xliff:g id="WHEN">%1$s</xliff:g>将不会听到下次闹钟响铃"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"要关闭移动数据网络吗?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"您将无法通过<xliff:g id="CARRIER">%s</xliff:g>使用移动数据或互联网,只能通过 WLAN 连接到互联网。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"您的运营商"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"切换回 <xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"移动流量不会根据可用性自动切换"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"不用了"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"是,切换"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"由于某个应用遮挡了权限请求界面,因此“设置”应用无法验证您的回应。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"要允许“<xliff:g id="APP_0">%1$s</xliff:g>”显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块吗?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- 可以读取“<xliff:g id="APP">%1$s</xliff:g>”中的信息"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"没有其他可用网络"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 75cc85b..9a5cbd2 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音助手"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 碼掃瞄器"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"解鎖"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已上鎖"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃瞄緊面孔"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"傳送"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"無法辨識面孔"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電量百分比不明。"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛航模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"開咗 VPN。"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"電量仲剩番 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你嘅使用情況,仲可以用大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"正在充電:<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%。"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"睇所有通知"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter (TTY) 已啟用。"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"鈴聲震動。"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"繼續"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或錄製應用程式"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"要允許此應用程式分享或錄製內容嗎?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"進行分享、錄製或投放時,此應用程式可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"進行分享、錄製或投放時,此應用程式可存取顯示在螢幕畫面上或在該應用程式上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"已被您的 IT 管理員封鎖"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"螢幕截圖功能因裝置政策而停用"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"擷取資訊卡時發生問題,請稍後再試。"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"上鎖畫面設定"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"掃瞄 QR 碼"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"您不會<xliff:g id="WHEN">%1$s</xliff:g>聽到鬧鐘"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"要關閉流動數據嗎?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"您無法透過「<xliff:g id="CARRIER">%s</xliff:g>」使用流動數據或互聯網。如要使用互聯網,您必須連接 Wi-Fi。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"您的流動網絡供應商"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"要切換回「<xliff:g id="CARRIER">%s</xliff:g>」嗎?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"流動數據不會根據可用性自動切換"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"不用了,謝謝"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"是,切換回 DDS 對話框"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- 可以讀取「<xliff:g id="APP">%1$s</xliff:g>」中的資料"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時連線"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"連線速度欠佳"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"不會自動連線至流動數據"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有連線"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網絡"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ae8e6db..9a31504 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR code 掃描器"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃描臉孔"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"傳送"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"無法辨識臉孔"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池電量不明。"</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛行模式。"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已開啟。"</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"目前的電量為 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你的使用情形,大約還能使用到<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"充電中,已完成 <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%。"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"查看所有通知"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter (TTY) 已啟用。"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"鈴聲震動。"</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放應用程式時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"繼續"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或錄製應用程式"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"要允許這個應用程式分享或錄製嗎?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"進行分享、錄製或投放時,這個應用程式可以存取螢幕畫面上所顯示或裝置上所播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"進行分享、錄製或投放應用程式時,這個應用程式可以存取在其中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT 管理員已封鎖這項操作"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"根據裝置政策規定,螢幕畫面擷取功能已停用"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"擷取卡片時發生問題,請稍後再試"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"螢幕鎖定設定"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"掃描 QR 圖碼"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"要關閉行動數據嗎?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"你將無法透過「<xliff:g id="CARRIER">%s</xliff:g>」使用行動數據或網際網路。你只能透過 Wi-Fi 使用網際網路。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"你的電信業者"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"要切換回「<xliff:g id="CARRIER">%s</xliff:g>」嗎?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"行動數據不會依據可用性自動切換"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"不用了,謝謝"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"是,切換回 DDS 對話方塊"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"由於某個應用程式覆蓋了權限要求畫面,因此「設定」應用程式無法驗證你的回應。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊嗎?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- 它可以讀取「<xliff:g id="APP">%1$s</xliff:g>」的資訊"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時建立連線"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"連線品質不佳"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"系統將不會自動使用行動數據連線"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有網路連線"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網路"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0ce0613..36f94ae 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -125,7 +125,8 @@
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Isisekeli sezwi"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"I-wallet"</string>
     <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Iskena sekhodi ye-QR"</string>
-    <string name="accessibility_unlock_button" msgid="122785427241471085">"Vula"</string>
+    <!-- no translation found for accessibility_unlock_button (3613812140816244310) -->
+    <skip />
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Idivayisi ikhiyiwe"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Ukuskena ubuso"</string>
     <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Thumela"</string>
@@ -168,7 +169,7 @@
     <skip />
     <string name="keyguard_face_failed" msgid="9044619102286917151">"Ayikwazi ukubona ubuso"</string>
     <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kunalokho sebenzisa isigxivizo somunwe"</string>
-    <!-- no translation found for keyguard_face_unlock_unavailable (8145547300240405980) -->
+    <!-- no translation found for keyguard_face_unlock_unavailable (1581949044193418736) -->
     <skip />
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ixhunyiwe"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Iphesenti lebhethri alaziwa."</string>
@@ -180,8 +181,13 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Imodi yendiza."</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"I-VPN ivuliwe."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Iphesenti <xliff:g id="NUMBER">%d</xliff:g> lebhethri"</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Amaphesenti ebhethri ngu-<xliff:g id="PERCENTAGE">%1$s</xliff:g>, cishe kusele okungu-<xliff:g id="TIME">%2$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
+    <!-- no translation found for accessibility_battery_level_with_estimate (6548654589315074529) -->
+    <skip />
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Ibhethri liyashaja, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%"</string>
+    <!-- no translation found for accessibility_battery_level_charging_paused (3560711496775146763) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level_charging_paused_with_estimate (2223541217743647858) -->
+    <skip />
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Bona zonke izaziso"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"i-TeleTypewriter inikwe amandla"</string>
     <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Ukudlidliza kweringa."</string>
@@ -375,16 +381,11 @@
     <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Uma wabelana, urekhoda, noma usakaza i-app, i-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inokufinyelela kunoma yini eboniswayo noma edlalwayo kuleyo app. Ngakho-ke qaphela amagama ayimfihlo, imininingwane yokukhokha, imiyalezo, noma olunye ulwazi olubucayi."</string>
     <string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Qhubeka"</string>
     <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Yabelana noma rekhoda i-app"</string>
-    <!-- no translation found for media_projection_permission_dialog_system_service_title (6827129613741303726) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_entire_screen (8801616203805837575) -->
-    <skip />
-    <!-- no translation found for media_projection_permission_dialog_system_service_warning_single_app (543310680568419338) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_title (2113331792064527203) -->
-    <skip />
-    <!-- no translation found for screen_capturing_disabled_by_policy_dialog_description (6015975736747696431) -->
-    <skip />
+    <string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vumela le-app ukwabelana noma ukurekhoda?"</string>
+    <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Uma wabelana, urekhoda, noma usakaza, le-app inokufinyelela kunoma yini ebonakalayo kusikrini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela amagama ayimfihlo, imininingwane yokukhokha, imiyalezo, noma olunye ulwazi olubucayi."</string>
+    <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Uma wabelana, urekhoda, noma usakaza i-app, le-app inokufinyelela kunoma yini eboniswayo noma edlalwayo kuleyo app. Ngakho-ke qaphela amagama ayimfihlo, imininingwane yokukhokha, imiyalezo, noma olunye ulwazi olubucayi."</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Kuvinjelwe ngumlawuli wakho we-IT"</string>
+    <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Ukuthwebula isikrini kukhutshazwe yinqubomgomo yedivayisi"</string>
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Sula konke"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Phatha"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Umlando"</string>
@@ -500,7 +501,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Vula ukuze usebenzise"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kube khona inkinga yokuthola amakhadi akho, sicela uzame futhi ngemuva kwesikhathi"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Amasethingi okukhiya isikrini"</string>
-    <string name="qr_code_scanner_title" msgid="5290201053875420785">"Skena ikhodi ye-QR"</string>
+    <!-- no translation found for qr_code_scanner_title (1938155688725760702) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -739,6 +741,10 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Vala idatha yeselula?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"Ngeke ube nokufinyelela kudatha noma ku-inthanethi nge-<xliff:g id="CARRIER">%s</xliff:g>. I-inthanethi izotholakala kuphela nge-Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"inkampani yakho yenethiwekhi"</string>
+    <string name="auto_data_switch_disable_title" msgid="5146527155665190652">"Shintshela emuva ku-<xliff:g id="CARRIER">%s</xliff:g>?"</string>
+    <string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Idatha yeselula ngeke ishintshe ngokuzenzakalelayo ngokusekelwe ekutholakaleni"</string>
+    <string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Cha ngiyabonga"</string>
+    <string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Yebo, shintsha"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Ngoba uhlelo lokusebenza lusitha isicelo semvume, Izilungiselelo azikwazi ukuqinisekisa impendulo yakho."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Vumela i-<xliff:g id="APP_0">%1$s</xliff:g> ukuthi ibonise izingcezu ze-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- Ingafunda ulwazi kusukela ku-<xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -929,6 +935,8 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ixhume okwesikhashana"</string>
+    <string name="mobile_data_poor_connection" msgid="819617772268371434">"Uxhumo olungeluhle"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Idatha yeselula ngeke ikwazi ukuxhuma ngokuzenzekelayo"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Alukho uxhumano"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Awekho amanye amanethiwekhi atholakalayo"</string>
diff --git a/packages/SystemUI/res/values/bools.xml b/packages/SystemUI/res/values/bools.xml
index 8221d78..04fc4b8 100644
--- a/packages/SystemUI/res/values/bools.xml
+++ b/packages/SystemUI/res/values/bools.xml
@@ -25,6 +25,9 @@
     <!-- Whether to enable clipping on Quick Settings -->
     <bool name="qs_enable_clipping">true</bool>
 
+    <!-- Whether to enable clipping on Notification Views -->
+    <bool name="notification_enable_clipping">true</bool>
+
     <!-- Whether to enable transparent background for notification scrims -->
     <bool name="notification_scrim_transparent">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index ce9829b..7a36204 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -485,6 +485,12 @@
     <!-- Whether to show a severe low battery dialog. -->
     <bool name="config_severe_battery_dialog">false</bool>
 
+    <!-- A path representing a shield. Will sometimes be displayed with the battery icon when
+         needed. This path is a 10px wide and 13px tall. -->
+    <string name="config_batterymeterShieldPath" translatable="false">
+        M5 0L0 1.88V6.19C0 9.35 2.13 12.29 5 13.01C7.87 12.29 10 9.35 10 6.19V1.88L5 0Z
+    </string>
+
     <!-- A path similar to frameworks/base/core/res/res/values/config.xml
       config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display
       cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then
@@ -737,12 +743,35 @@
     <!-- How long in milliseconds before full burn-in protection is achieved. -->
     <integer name="config_dreamOverlayMillisUntilFullJitter">240000</integer>
 
+    <!-- The duration in milliseconds of the y-translation animation when waking up from
+         the dream -->
+    <integer name="config_dreamOverlayOutTranslationYDurationMs">333</integer>
+    <!-- The delay in milliseconds of the y-translation animation when waking up from
+         the dream for the complications at the bottom of the screen -->
+    <integer name="config_dreamOverlayOutTranslationYDelayBottomMs">33</integer>
+    <!-- The delay in milliseconds of the y-translation animation when waking up from
+         the dream for the complications at the top of the screen -->
+    <integer name="config_dreamOverlayOutTranslationYDelayTopMs">117</integer>
+    <!-- The duration in milliseconds of the alpha animation when waking up from the dream -->
+    <integer name="config_dreamOverlayOutAlphaDurationMs">200</integer>
+    <!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
+         complications at the top of the screen -->
+    <integer name="config_dreamOverlayOutAlphaDelayTopMs">217</integer>
+    <!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
+         complications at the bottom of the screen -->
+    <integer name="config_dreamOverlayOutAlphaDelayBottomMs">133</integer>
+    <!-- The duration in milliseconds of the blur animation when waking up from
+         the dream -->
+    <integer name="config_dreamOverlayOutBlurDurationMs">250</integer>
+
     <integer name="complicationFadeOutMs">500</integer>
 
     <integer name="complicationFadeInMs">500</integer>
 
     <integer name="complicationRestoreMs">1000</integer>
 
+    <integer name="complicationFadeOutDelayMs">200</integer>
+
     <!-- Duration in milliseconds of the dream in un-blur animation. -->
     <integer name="config_dreamOverlayInBlurDurationMs">249</integer>
     <!-- Delay in milliseconds of the dream in un-blur animation. -->
@@ -774,28 +803,27 @@
         <item>com.android.systemui</item>
     </string-array>
 
-    <!-- The thresholds which determine the color used by the AQI dream overlay.
-         NOTE: This must always be kept sorted from low to high -->
-    <integer-array name="config_dreamAqiThresholds">
-        <item>-1</item>
-        <item>50</item>
-        <item>100</item>
-        <item>150</item>
-        <item>200</item>
-        <item>300</item>
-    </integer-array>
-
-    <!-- The color values which correspond to the thresholds above -->
-    <integer-array name="config_dreamAqiColorValues">
-        <item>@color/dream_overlay_aqi_good</item>
-        <item>@color/dream_overlay_aqi_moderate</item>
-        <item>@color/dream_overlay_aqi_unhealthy_sensitive</item>
-        <item>@color/dream_overlay_aqi_unhealthy</item>
-        <item>@color/dream_overlay_aqi_very_unhealthy</item>
-        <item>@color/dream_overlay_aqi_hazardous</item>
-    </integer-array>
-
     <!-- Whether the device should display hotspot UI. If true, UI will display only when tethering
          is available. If false, UI will never show regardless of tethering availability" -->
     <bool name="config_show_wifi_tethering">true</bool>
+
+    <!-- A collection of "slots" for placing quick affordance actions on the lock screen when the
+    device is locked. Each item is a string consisting of two parts, separated by the ':' character.
+    The first part is the unique ID for the slot, it is not a human-visible name, but should still
+    be unique across all slots specified. The second part is the capacity and must be a positive
+    integer; this is how many quick affordance actions that user is allowed to add to the slot. -->
+    <string-array name="config_keyguardQuickAffordanceSlots" translatable="false">
+        <item>bottom_start:1</item>
+        <item>bottom_end:1</item>
+    </string-array>
+
+    <!-- A collection of defaults for the quick affordances on the lock screen. Each item must be a
+    string with two parts: the ID of the slot and the comma-delimited list of affordance IDs,
+    separated by a colon ':' character. For example: <item>bottom_end:home,wallet</item>. The
+    default is displayed by System UI as long as the user hasn't made a different choice for that
+    slot. If the user did make a choice, even if the choice is the "None" option, the default is
+    ignored. -->
+    <string-array name="config_keyguardQuickAffordanceDefaults" translatable="false">
+    </string-array>
+
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e8ae929..7cda9d7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -105,6 +105,12 @@
     so the width of the icon should be 13.0dp * (12.0 / 20.0) -->
     <dimen name="status_bar_battery_icon_width">7.8dp</dimen>
 
+    <!-- The battery icon is 13dp tall, but the other system icons are 15dp tall (see
+         @*android:dimen/status_bar_system_icon_size) with some top and bottom padding embedded in
+         the drawables themselves. So, the battery icon may need an extra 1dp of spacing so that its
+         bottom still aligns with the bottom of all the other system icons. See b/258672854. -->
+    <dimen name="status_bar_battery_extra_vertical_spacing">1dp</dimen>
+
     <!-- The font size for the clock in the status bar. -->
     <dimen name="status_bar_clock_size">14sp</dimen>
 
@@ -1478,10 +1484,12 @@
 
     <!-- Dream overlay complications related dimensions -->
     <dimen name="dream_overlay_complication_clock_time_text_size">86sp</dimen>
+    <dimen name="dream_overlay_complication_clock_time_padding">20dp</dimen>
     <dimen name="dream_overlay_complication_clock_subtitle_text_size">24sp</dimen>
     <dimen name="dream_overlay_complication_preview_text_size">36sp</dimen>
     <dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen>
     <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen>
+    <dimen name="dream_overlay_complication_smartspace_padding">24dp</dimen>
 
     <!-- The position of the end guide, which dream overlay complications can align their start with
          if their end is aligned with the parent end. Represented as the percentage over from the
@@ -1526,6 +1534,7 @@
     <dimen name="dream_overlay_complication_margin">0dp</dimen>
 
     <dimen name="dream_overlay_y_offset">80dp</dimen>
+    <dimen name="dream_overlay_exit_y_offset">40dp</dimen>
 
     <dimen name="dream_aqi_badge_corner_radius">28dp</dimen>
     <dimen name="dream_aqi_badge_padding_vertical">6dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 72305c6..400235a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -316,7 +316,7 @@
     <!-- Content description of the QR Code scanner for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_qr_code_scanner_button">QR Code Scanner</string>
     <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button">Unlock</string>
+    <string name="accessibility_unlock_button">Unlocked</string>
     <!-- Content description of the lock icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_lock_icon">Device locked</string>
     <!-- Content description hint of the unlock button when fingerprint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -405,8 +405,8 @@
     <string name="keyguard_face_failed">Can\u2019t recognize face</string>
     <!-- Message shown to suggest using fingerprint sensor to authenticate after another biometric failed. [CHAR LIMIT=25] -->
     <string name="keyguard_suggest_fingerprint">Use fingerprint instead</string>
-    <!-- Message shown to inform the user that face unlock is not available. [CHAR LIMIT=25] -->
-    <string name="keyguard_face_unlock_unavailable">Face unlock unavailable.</string>
+    <!-- Message shown to inform the user that face unlock is not available. [CHAR LIMIT=59] -->
+    <string name="keyguard_face_unlock_unavailable">Face Unlock unavailable</string>
 
     <!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
@@ -439,11 +439,17 @@
     <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
 
     <!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$s</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
+    <string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$d</xliff:g> percent, <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g></string>
 
     <!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
 
+    <!-- Content description of the battery level icon for accessibility, with information that the device charging is paused in order to protect the lifetime of the battery (not shown on screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_level_charging_paused">Battery <xliff:g id="percentage" example="90%">%d</xliff:g> percent, charging paused for battery protection.</string>
+
+    <!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery *and* information that the device charging is paused in order to protect the lifetime of the battery (not shown on screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_level_charging_paused_with_estimate">Battery <xliff:g id="percentage" example="90%">%1$d</xliff:g> percent, <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g>, charging paused for battery protection.</string>
+
     <!-- Content description of overflow icon container of the notifications for accessibility (not shown on the screen)[CHAR LIMIT=NONE] -->
     <string name="accessibility_overflow_action">See all notifications</string>
 
@@ -2041,6 +2047,15 @@
     <!-- Text used to refer to the user's current carrier in mobile_data_disable_message if the users's mobile network carrier name is not available [CHAR LIMIT=NONE] -->
     <string name="mobile_data_disable_message_default_carrier">your carrier</string>
 
+    <!-- Title of the dialog to turn off data usage [CHAR LIMIT=NONE] -->
+    <string name="auto_data_switch_disable_title">Switch back to <xliff:g id="carrier" example="T-Mobile">%s</xliff:g>?</string>
+    <!-- Message body of the dialog to turn off data usage [CHAR LIMIT=NONE] -->
+    <string name="auto_data_switch_disable_message">Mobile data won\’t automatically switch based on availability</string>
+    <!-- Negative button title of the quick settings switch back to DDS dialog [CHAR LIMIT=NONE] -->
+    <string name="auto_data_switch_dialog_negative_button">No thanks</string>
+    <!-- Positive button title of the quick settings switch back to DDS dialog [CHAR LIMIT=NONE] -->
+    <string name="auto_data_switch_dialog_positive_button">Yes, switch</string>
+
     <!-- Warning shown when user input has been blocked due to another app overlaying screen
      content. Since we don't know what the app is showing on top of the input target, we
      can't verify user consent. [CHAR LIMIT=NONE] -->
@@ -2511,6 +2526,12 @@
          Summary indicating that a SIM has an active mobile data connection [CHAR LIMIT=50] -->
     <string name="mobile_data_connection_active">Connected</string>
     <!-- Provider Model:
+         Summary indicating that a SIM is temporarily connected to mobile data [CHAR LIMIT=50] -->
+    <string name="mobile_data_temp_connection_active">Temporarily connected</string>
+    <!-- Provider Model:
+     Summary indicating that a SIM is temporarily connected to mobile data [CHAR LIMIT=50] -->
+    <string name="mobile_data_poor_connection">Poor connection</string>
+    <!-- Provider Model:
      Summary indicating that a SIM has no mobile data connection [CHAR LIMIT=50] -->
     <string name="mobile_data_off_summary">Mobile data won\u0027t auto\u2011connect</string>
     <!-- Provider Model:
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff29039..dea06b7 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -1095,7 +1095,7 @@
         <item name="android:orientation">horizontal</item>
         <item name="android:focusable">true</item>
         <item name="android:clickable">true</item>
-        <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:background">@drawable/internet_dialog_selected_effect</item>
     </style>
 
     <style name="InternetDialog.NetworkTitle">
diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml
index 148e5ec..1eb621e 100644
--- a/packages/SystemUI/res/xml/media_session_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_session_collapsed.xml
@@ -44,6 +44,16 @@
         app:layout_constraintTop_toTopOf="@+id/album_art"
         app:layout_constraintBottom_toBottomOf="@+id/album_art" />
 
+    <!-- Turbulence noise must have the same constraint as the album art. -->
+    <Constraint
+        android:id="@+id/turbulence_noise_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_collapsed"
+        app:layout_constraintStart_toStartOf="@+id/album_art"
+        app:layout_constraintEnd_toEndOf="@+id/album_art"
+        app:layout_constraintTop_toTopOf="@+id/album_art"
+        app:layout_constraintBottom_toBottomOf="@+id/album_art" />
+
     <Constraint
         android:id="@+id/header_title"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index ac484d7..64c2ef1 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -37,6 +37,16 @@
         app:layout_constraintTop_toTopOf="@+id/album_art"
         app:layout_constraintBottom_toBottomOf="@+id/album_art" />
 
+    <!-- Turbulence noise must have the same constraint as the album art. -->
+    <Constraint
+        android:id="@+id/turbulence_noise_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_media_session_height_expanded"
+        app:layout_constraintStart_toStartOf="@+id/album_art"
+        app:layout_constraintEnd_toEndOf="@+id/album_art"
+        app:layout_constraintTop_toTopOf="@+id/album_art"
+        app:layout_constraintBottom_toBottomOf="@+id/album_art" />
+
     <Constraint
         android:id="@+id/header_title"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/xml/qqs_header.xml b/packages/SystemUI/res/xml/qqs_header.xml
index af4be1a..5d3650c 100644
--- a/packages/SystemUI/res/xml/qqs_header.xml
+++ b/packages/SystemUI/res/xml/qqs_header.xml
@@ -25,7 +25,7 @@
         android:id="@+id/clock">
         <Layout
             android:layout_width="wrap_content"
-            android:layout_height="0dp"
+            android:layout_height="@dimen/large_screen_shade_header_min_height"
             app:layout_constraintStart_toStartOf="@id/begin_guide"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -42,7 +42,7 @@
     <Constraint
         android:id="@+id/date">
         <Layout
-            android:layout_width="0dp"
+            android:layout_width="wrap_content"
             android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
             android:layout_marginStart="8dp"
             app:layout_constrainedWidth="true"
@@ -57,14 +57,16 @@
     <Constraint
         android:id="@+id/statusIcons">
         <Layout
-            android:layout_width="0dp"
+            android:layout_width="wrap_content"
             android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
+            app:layout_constrainedWidth="true"
             app:layout_constraintHeight_min="@dimen/new_qs_header_non_clickable_element_height"
             app:layout_constraintStart_toEndOf="@id/date"
             app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintHorizontal_bias="1"
+            app:layout_constraintHorizontal_chainStyle="packed"
             />
     </Constraint>
 
@@ -80,12 +82,16 @@
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintHorizontal_bias="1"
+            app:layout_constraintHorizontal_chainStyle="packed"
             />
     </Constraint>
 
     <Constraint
         android:id="@+id/carrier_group">
         <Layout
+            app:layout_constraintWidth_min="48dp"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/large_screen_shade_header_min_height"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintTop_toTopOf="parent"
             />
diff --git a/packages/SystemUI/res/xml/qs_header_new.xml b/packages/SystemUI/res/xml/qs_header_new.xml
index d8a4e77..982c422 100644
--- a/packages/SystemUI/res/xml/qs_header_new.xml
+++ b/packages/SystemUI/res/xml/qs_header_new.xml
@@ -43,6 +43,7 @@
             app:layout_constraintBottom_toBottomOf="@id/carrier_group"
             app:layout_constraintEnd_toStartOf="@id/carrier_group"
             app:layout_constraintHorizontal_bias="0"
+            app:layout_constraintHorizontal_chainStyle="spread_inside"
         />
         <Transform
             android:scaleX="2.57"
@@ -53,7 +54,7 @@
     <Constraint
         android:id="@+id/date">
         <Layout
-            android:layout_width="0dp"
+            android:layout_width="wrap_content"
             android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toStartOf="@id/space"
@@ -67,16 +68,15 @@
     <Constraint
         android:id="@+id/carrier_group">
         <Layout
-            app:layout_constraintHeight_min="@dimen/large_screen_shade_header_min_height"
-            android:minHeight="@dimen/large_screen_shade_header_min_height"
             app:layout_constraintWidth_min="48dp"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/large_screen_shade_header_min_height"
             app:layout_constraintStart_toEndOf="@id/clock"
             app:layout_constraintTop_toBottomOf="@id/privacy_container"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintHorizontal_bias="1"
             app:layout_constraintBottom_toTopOf="@id/batteryRemainingIcon"
+            app:layout_constraintHorizontal_chainStyle="spread_inside"
             />
         <PropertySet
             android:alpha="1"
@@ -86,7 +86,7 @@
     <Constraint
         android:id="@+id/statusIcons">
         <Layout
-            android:layout_width="0dp"
+            android:layout_width="wrap_content"
             android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
             app:layout_constrainedWidth="true"
             app:layout_constraintStart_toEndOf="@id/space"
@@ -108,6 +108,7 @@
             app:layout_constraintTop_toTopOf="@id/date"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintHorizontal_bias="1"
+            app:layout_constraintHorizontal_chainStyle="spread_inside"
             />
     </Constraint>
 
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 485a0d3..b679cfa1 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -52,23 +52,14 @@
         "SystemUIUnfoldLib",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx.concurrent_concurrent-futures",
-        "androidx.lifecycle_lifecycle-runtime-ktx",
-        "androidx.lifecycle_lifecycle-viewmodel-ktx",
-        "androidx.recyclerview_recyclerview",
-        "kotlinx_coroutines_android",
-        "kotlinx_coroutines",
         "dagger2",
         "jsr330",
     ],
     resource_dirs: [
         "res",
     ],
-    optimize: {
-        proguard_flags_files: ["proguard.flags"],
-    },
     min_sdk_version: "current",
     plugins: ["dagger2-compiler"],
-    kotlincflags: ["-Xjvm-default=enable"],
 }
 
 java_library {
diff --git a/packages/SystemUI/shared/proguard.flags b/packages/SystemUI/shared/proguard.flags
deleted file mode 100644
index 5eda045..0000000
--- a/packages/SystemUI/shared/proguard.flags
+++ /dev/null
@@ -1,4 +0,0 @@
-# Retain signatures of TypeToken and its subclasses for gson usage in ClockRegistry
--keepattributes Signature
--keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
--keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index ca780c8..23a7271 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -20,6 +20,7 @@
 import android.icu.text.NumberFormat
 import android.util.TypedValue
 import android.view.LayoutInflater
+import android.view.View
 import android.widget.FrameLayout
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.plugins.ClockAnimations
@@ -80,7 +81,7 @@
     }
 
     override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
-        largeClock.recomputePadding()
+        largeClock.recomputePadding(null)
         animations = DefaultClockAnimations(dozeFraction, foldFraction)
         events.onColorPaletteChanged(resources)
         events.onTimeZoneChanged(TimeZone.getDefault())
@@ -101,6 +102,7 @@
         // MAGENTA is a placeholder, and will be assigned correctly in initialize
         private var currentColor = Color.MAGENTA
         private var isRegionDark = false
+        protected var targetRegion: Rect? = null
 
         init {
             view.setColors(currentColor, currentColor)
@@ -112,8 +114,20 @@
                     this@DefaultClockFaceController.isRegionDark = isRegionDark
                     updateColor()
                 }
+
+                override fun onTargetRegionChanged(targetRegion: Rect?) {
+                    this@DefaultClockFaceController.targetRegion = targetRegion
+                    recomputePadding(targetRegion)
+                }
+
+                override fun onFontSettingChanged(fontSizePx: Float) {
+                    view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizePx)
+                    recomputePadding(targetRegion)
+                }
             }
 
+        open fun recomputePadding(targetRegion: Rect?) {}
+
         fun updateColor() {
             val color =
                 if (isRegionDark) {
@@ -128,16 +142,25 @@
 
             currentColor = color
             view.setColors(DOZE_COLOR, color)
-            view.animateAppearOnLockscreen()
+            if (!animations.dozeState.isActive) {
+                view.animateAppearOnLockscreen()
+            }
         }
     }
 
     inner class LargeClockFaceController(
         view: AnimatableClockView,
     ) : DefaultClockFaceController(view) {
-        fun recomputePadding() {
+        override fun recomputePadding(targetRegion: Rect?) {
+            // We center the view within the targetRegion instead of within the parent
+            // view by computing the difference and adding that to the padding.
+            val parent = view.parent
+            val yDiff =
+                if (targetRegion != null && parent is View && parent.isLaidOut())
+                    targetRegion.centerY() - parent.height / 2f
+                else 0f
             val lp = view.getLayoutParams() as FrameLayout.LayoutParams
-            lp.topMargin = (-0.5f * view.bottom).toInt()
+            lp.topMargin = (-0.5f * view.bottom + yDiff).toInt()
             view.setLayoutParams(lp)
         }
 
@@ -155,18 +178,6 @@
         override fun onTimeZoneChanged(timeZone: TimeZone) =
             clocks.forEach { it.onTimeZoneChanged(timeZone) }
 
-        override fun onFontSettingChanged() {
-            smallClock.view.setTextSize(
-                TypedValue.COMPLEX_UNIT_PX,
-                resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
-            )
-            largeClock.view.setTextSize(
-                TypedValue.COMPLEX_UNIT_PX,
-                resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
-            )
-            largeClock.recomputePadding()
-        }
-
         override fun onColorPaletteChanged(resources: Resources) {
             largeClock.updateColor()
             smallClock.updateColor()
@@ -188,7 +199,7 @@
         dozeFraction: Float,
         foldFraction: Float,
     ) : ClockAnimations {
-        private val dozeState = AnimationState(dozeFraction)
+        internal val dozeState = AnimationState(dozeFraction)
         private val foldState = AnimationState(foldFraction)
 
         init {
@@ -229,7 +240,7 @@
             get() = true
     }
 
-    private class AnimationState(
+    class AnimationState(
         var fraction: Float,
     ) {
         var isActive: Boolean = fraction > 0.5f
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/keyguard/data/content/KeyguardQuickAffordanceProviderContract.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/keyguard/data/content/KeyguardQuickAffordanceProviderContract.kt
new file mode 100644
index 0000000..f60db2a
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/keyguard/data/content/KeyguardQuickAffordanceProviderContract.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.shared.keyguard.data.content
+
+import android.content.ContentResolver
+import android.net.Uri
+
+/** Contract definitions for querying content about keyguard quick affordances. */
+object KeyguardQuickAffordanceProviderContract {
+
+    const val AUTHORITY = "com.android.systemui.keyguard.quickaffordance"
+    const val PERMISSION = "android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
+
+    private val BASE_URI: Uri =
+        Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build()
+
+    /**
+     * Table for slots.
+     *
+     * Slots are positions where affordances can be placed on the lock screen. Affordances that are
+     * placed on slots are said to be "selected". The system supports the idea of multiple
+     * affordances per slot, though the implementation may limit the number of affordances on each
+     * slot.
+     *
+     * Supported operations:
+     * - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result set
+     * will contain rows with the [SlotTable.Columns] columns.
+     */
+    object SlotTable {
+        const val TABLE_NAME = "slots"
+        val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
+
+        object Columns {
+            /** String. Unique ID for this slot. */
+            const val ID = "id"
+            /** Integer. The maximum number of affordances that can be placed in the slot. */
+            const val CAPACITY = "capacity"
+        }
+    }
+
+    /**
+     * Table for affordances.
+     *
+     * Affordances are actions/buttons that the user can execute. They are placed on slots on the
+     * lock screen.
+     *
+     * Supported operations:
+     * - Query - to know about all the affordances that are available on the device, regardless of
+     * which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result set will
+     * contain rows, each with the columns specified in [AffordanceTable.Columns].
+     */
+    object AffordanceTable {
+        const val TABLE_NAME = "affordances"
+        val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
+
+        object Columns {
+            /** String. Unique ID for this affordance. */
+            const val ID = "id"
+            /** String. User-visible name for this affordance. */
+            const val NAME = "name"
+            /**
+             * Integer. Resource ID for the drawable to load for this affordance. This is a resource
+             * ID from the system UI package.
+             */
+            const val ICON = "icon"
+        }
+    }
+
+    /**
+     * Table for selections.
+     *
+     * Selections are pairs of slot and affordance IDs.
+     *
+     * Supported operations:
+     * - Insert - to insert an affordance and place it in a slot, insert values for the columns into
+     * the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
+     * Selecting a new affordance for a slot that is already full will automatically remove the
+     * oldest affordance from the slot.
+     * - Query - to know which affordances are set on which slots, query the [SelectionTable.URI]
+     * [Uri]. The result set will contain rows, each of which with the columns from
+     * [SelectionTable.Columns].
+     * - Delete - to unselect an affordance, removing it from a slot, delete from the
+     * [SelectionTable.URI] [Uri], passing in values for each column.
+     */
+    object SelectionTable {
+        const val TABLE_NAME = "selections"
+        val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
+
+        object Columns {
+            /** String. Unique ID for the slot. */
+            const val SLOT_ID = "slot_id"
+            /** String. Unique ID for the selected affordance. */
+            const val AFFORDANCE_ID = "affordance_id"
+        }
+    }
+
+    /**
+     * Table for flags.
+     *
+     * Flags are key-value pairs.
+     *
+     * Supported operations:
+     * - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
+     * contain rows, each of which with the columns from [FlagsTable.Columns].
+     */
+    object FlagsTable {
+        const val TABLE_NAME = "flags"
+        val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
+
+        /**
+         * Flag denoting whether the customizable lock screen quick affordances feature is enabled.
+         */
+        const val FLAG_NAME_FEATURE_ENABLED = "is_feature_enabled"
+
+        object Columns {
+            /** String. Unique ID for the flag. */
+            const val NAME = "name"
+            /** Int. Value of the flag. `1` means `true` and `0` means `false`. */
+            const val VALUE = "value"
+        }
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index 40c8774..f45887c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -61,25 +61,42 @@
      * Updates the matrix based on the provided parameters
      */
     public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
-            int canvasWidth, int canvasHeight, int screenWidthPx, int taskbarSize, boolean isTablet,
+            int canvasWidth, int canvasHeight, int screenWidthPx, int screenHeightPx,
+            int taskbarSize, boolean isTablet,
             int currentRotation, boolean isRtl) {
         boolean isRotated = false;
         boolean isOrientationDifferent;
 
-        float fullscreenTaskWidth = screenWidthPx;
-        if (mSplitBounds != null && !mSplitBounds.appsStackedVertically) {
-            // For landscape, scale the width
-            float taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT
-                    ? mSplitBounds.leftTaskPercent
-                    : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent));
-            // Scale landscape width to that of actual screen
-            fullscreenTaskWidth = screenWidthPx * taskPercent;
-        }
         int thumbnailRotation = thumbnailData.rotation;
         int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
         RectF thumbnailClipHint = new RectF();
-        float canvasScreenRatio = canvasWidth / fullscreenTaskWidth;
-        float scaledTaskbarSize = taskbarSize * canvasScreenRatio;
+
+        float scaledTaskbarSize;
+        float canvasScreenRatio;
+        if (mSplitBounds != null) {
+            float fullscreenTaskWidth;
+            float fullscreenTaskHeight;
+
+            float taskPercent;
+            if (mSplitBounds.appsStackedVertically) {
+                taskPercent = mDesiredStagePosition != STAGE_POSITION_TOP_OR_LEFT
+                        ? mSplitBounds.topTaskPercent
+                        : (1 - (mSplitBounds.topTaskPercent + mSplitBounds.dividerHeightPercent));
+                fullscreenTaskHeight = screenHeightPx * taskPercent;
+                canvasScreenRatio = canvasHeight / fullscreenTaskHeight;
+            } else {
+                // For landscape, scale the width
+                taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT
+                        ? mSplitBounds.leftTaskPercent
+                        : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent));
+                // Scale landscape width to that of actual screen
+                fullscreenTaskWidth = screenWidthPx * taskPercent;
+                canvasScreenRatio = canvasWidth / fullscreenTaskWidth;
+            }
+        } else {
+            canvasScreenRatio = (float) canvasWidth / screenWidthPx;
+        }
+        scaledTaskbarSize = taskbarSize * canvasScreenRatio;
         thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0;
 
         float scale = thumbnailData.scale;
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
index 74519c2..05372fe 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
@@ -22,7 +22,11 @@
     private val flagMap = mutableMapOf<String, Flag<*>>()
 
     val knownFlags: Map<String, Flag<*>>
-        get() = flagMap
+        get() {
+            // We need to access Flags in order to initialize our map.
+            assert(flagMap.contains(Flags.TEAMFOOD.name)) { "Where is teamfood?" }
+            return flagMap
+        }
 
     fun unreleasedFlag(
         id: Int,
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index 7b216017..8323d09 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -34,6 +34,9 @@
     @Binds
     abstract fun bindsFeatureFlagDebug(impl: FeatureFlagsDebug): FeatureFlags
 
+    @Binds
+    abstract fun bindsRestarter(debugRestarter: FeatureFlagsDebugRestarter): Restarter
+
     @Module
     companion object {
         @JvmStatic
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
index 89c0786..27c5699 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
@@ -22,7 +22,11 @@
     private val flagMap = mutableMapOf<String, Flag<*>>()
 
     val knownFlags: Map<String, Flag<*>>
-        get() = flagMap
+        get() {
+            // We need to access Flags in order to initialize our map.
+            assert(flagMap.contains(Flags.TEAMFOOD.name)) { "Where is teamfood?" }
+            return flagMap
+        }
 
     fun unreleasedFlag(
         id: Int,
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index aef8876..87beff7 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -27,4 +27,7 @@
 abstract class FlagsModule {
     @Binds
     abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
+
+    @Binds
+    abstract fun bindsRestarter(debugRestarter: FeatureFlagsReleaseRestarter): Restarter
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index c9b8712..87e9d56 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -26,6 +26,7 @@
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.R
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -43,6 +44,11 @@
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
 import com.android.systemui.statusbar.policy.ConfigurationController
+import java.io.PrintWriter
+import java.util.Locale
+import java.util.TimeZone
+import java.util.concurrent.Executor
+import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.Job
@@ -50,11 +56,6 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.launch
-import java.io.PrintWriter
-import java.util.Locale
-import java.util.TimeZone
-import java.util.concurrent.Executor
-import javax.inject.Inject
 
 /**
  * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
@@ -84,6 +85,7 @@
 
                 value.initialize(resources, dozeAmount, 0f)
                 updateRegionSamplers(value)
+                updateFontSizes()
             }
         }
 
@@ -150,7 +152,7 @@
             mainExecutor,
             bgExecutor,
             regionSamplingEnabled,
-            updateFun = { updateColors() } )
+            updateColors)
     }
 
     var smallRegionSampler: RegionSampler? = null
@@ -166,7 +168,7 @@
         }
 
         override fun onDensityOrFontScaleChanged() {
-            clock?.events?.onFontSettingChanged()
+            updateFontSizes()
         }
     }
 
@@ -251,6 +253,13 @@
         largeRegionSampler?.stopRegionSampler()
     }
 
+    private fun updateFontSizes() {
+        clock?.smallClock?.events?.onFontSettingChanged(
+            resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat())
+        clock?.largeClock?.events?.onFontSettingChanged(
+            resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat())
+    }
+
     /**
      * Dump information for debugging
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 8ebad6c..40423cd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -5,6 +5,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -22,6 +23,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+
 /**
  * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
  */
@@ -46,6 +48,7 @@
      */
     private FrameLayout mSmallClockFrame;
     private FrameLayout mLargeClockFrame;
+    private ClockController mClock;
 
     private View mStatusArea;
     private int mSmartspaceTopOffset;
@@ -95,6 +98,8 @@
     }
 
     void setClock(ClockController clock, int statusBarState) {
+        mClock = clock;
+
         // Disconnect from existing plugin.
         mSmallClockFrame.removeAllViews();
         mLargeClockFrame.removeAllViews();
@@ -108,6 +113,35 @@
         Log.i(TAG, "Attached new clock views to switch");
         mSmallClockFrame.addView(clock.getSmallClock().getView());
         mLargeClockFrame.addView(clock.getLargeClock().getView());
+        updateClockTargetRegions();
+    }
+
+    void updateClockTargetRegions() {
+        if (mClock != null) {
+            if (mSmallClockFrame.isLaidOut()) {
+                int targetHeight =  getResources()
+                        .getDimensionPixelSize(R.dimen.small_clock_text_size);
+                mClock.getSmallClock().getEvents().onTargetRegionChanged(new Rect(
+                        mSmallClockFrame.getLeft(),
+                        mSmallClockFrame.getTop(),
+                        mSmallClockFrame.getRight(),
+                        mSmallClockFrame.getTop() + targetHeight));
+            }
+
+            if (mLargeClockFrame.isLaidOut()) {
+                int largeClockTopMargin = getResources()
+                        .getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin);
+                int targetHeight = getResources()
+                        .getDimensionPixelSize(R.dimen.large_clock_text_size) * 2;
+                int top = mLargeClockFrame.getHeight() / 2 - targetHeight / 2
+                        + largeClockTopMargin / 2;
+                mClock.getLargeClock().getEvents().onTargetRegionChanged(new Rect(
+                        mLargeClockFrame.getLeft(),
+                        top,
+                        mLargeClockFrame.getRight(),
+                        top + targetHeight));
+            }
+        }
     }
 
     private void updateClockViews(boolean useLargeClock, boolean animate) {
@@ -214,6 +248,10 @@
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
 
+        if (changed) {
+            post(() -> updateClockTargetRegions());
+        }
+
         if (mDisplayedClockSize != null && !mChildrenAreLaidOut) {
             post(() -> updateClockViews(mDisplayedClockSize == LARGE, mAnimateOnLayout));
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index d3cc7ed..789f621 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -77,7 +77,7 @@
     @KeyguardClockSwitch.ClockSize
     private int mCurrentClockSize = SMALL;
 
-    private int mKeyguardClockTopMargin = 0;
+    private int mKeyguardSmallClockTopMargin = 0;
     private final ClockRegistry.ClockChangeListener mClockChangedListener;
 
     private ViewGroup mStatusArea;
@@ -162,7 +162,7 @@
         mClockRegistry.registerClockChangeListener(mClockChangedListener);
         setClock(mClockRegistry.createCurrentClock());
         mClockEventController.registerListeners(mView);
-        mKeyguardClockTopMargin =
+        mKeyguardSmallClockTopMargin =
                 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
 
         if (mOnlyClock) {
@@ -244,10 +244,12 @@
      */
     public void onDensityOrFontScaleChanged() {
         mView.onDensityOrFontScaleChanged();
-        mKeyguardClockTopMargin =
+        mKeyguardSmallClockTopMargin =
                 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
+        mView.updateClockTargetRegions();
     }
 
+
     /**
      * Set which clock should be displayed on the keyguard. The other one will be automatically
      * hidden.
@@ -327,7 +329,7 @@
             return frameHeight / 2 + clockHeight / 2;
         } else {
             int clockHeight = clock.getSmallClock().getView().getHeight();
-            return clockHeight + statusBarHeaderHeight + mKeyguardClockTopMargin;
+            return clockHeight + statusBarHeaderHeight + mKeyguardSmallClockTopMargin;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index db64f05..2b660de 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -21,7 +21,6 @@
 import android.content.res.Resources;
 import android.media.AudioManager;
 import android.os.SystemClock;
-import android.service.trust.TrustAgentService;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.MathUtils;
@@ -68,30 +67,24 @@
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
-                public void onTrustGrantedWithFlags(int flags, int userId) {
-                    if (userId != KeyguardUpdateMonitor.getCurrentUser()) return;
-                    boolean bouncerVisible = mView.isVisibleToUser();
-                    boolean temporaryAndRenewable =
-                            (flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
-                            != 0;
-                    boolean initiatedByUser =
-                            (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0;
-                    boolean dismissKeyguard =
-                            (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0;
-
-                    if (initiatedByUser || dismissKeyguard) {
-                        if ((mViewMediatorCallback.isScreenOn() || temporaryAndRenewable)
-                                && (bouncerVisible || dismissKeyguard)) {
-                            if (!bouncerVisible) {
-                                // The trust agent dismissed the keyguard without the user proving
-                                // that they are present (by swiping up to show the bouncer). That's
-                                // fine if the user proved presence via some other way to the trust
-                                //agent.
-                                Log.i(TAG, "TrustAgent dismissed Keyguard.");
-                            }
-                            mSecurityCallback.dismiss(false /* authenticated */, userId,
-                                    /* bypassSecondaryLockScreen */ false, SecurityMode.Invalid);
-                        } else {
+                public void onTrustGrantedForCurrentUser(boolean dismissKeyguard,
+                        TrustGrantFlags flags, String message) {
+                    if (dismissKeyguard) {
+                        if (!mView.isVisibleToUser()) {
+                            // The trust agent dismissed the keyguard without the user proving
+                            // that they are present (by swiping up to show the bouncer). That's
+                            // fine if the user proved presence via some other way to the trust
+                            // agent.
+                            Log.i(TAG, "TrustAgent dismissed Keyguard.");
+                        }
+                        mSecurityCallback.dismiss(
+                                false /* authenticated */,
+                                KeyguardUpdateMonitor.getCurrentUser(),
+                                /* bypassSecondaryLockScreen */ false,
+                                SecurityMode.Invalid
+                        );
+                    } else {
+                        if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
                             mViewMediatorCallback.playTrustedSound();
                         }
                     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 73229c3..faaba63 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -21,6 +21,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.inputmethod.InputMethodManager;
 
@@ -152,7 +153,9 @@
     }
 
     public void startAppearAnimation() {
-        mMessageAreaController.setMessage(getInitialMessageResId());
+        if (TextUtils.isEmpty(mMessageAreaController.getMessage())) {
+            mMessageAreaController.setMessage(getInitialMessageResId());
+        }
         mView.startAppearAnimation();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index a0206f1..8197685 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -50,10 +50,9 @@
     override val listening: Boolean,
     // keep sorted
     val authInterruptActive: Boolean,
-    val becauseCannotSkipBouncer: Boolean,
     val biometricSettingEnabledForUser: Boolean,
     val bouncerFullyShown: Boolean,
-    val faceAuthenticated: Boolean,
+    val faceAndFpNotAuthenticated: Boolean,
     val faceDisabled: Boolean,
     val faceLockedOut: Boolean,
     val fpLockedOut: Boolean,
@@ -67,7 +66,9 @@
     val secureCameraLaunched: Boolean,
     val switchingUser: Boolean,
     val udfpsBouncerShowing: Boolean,
-) : KeyguardListenModel()
+    val udfpsFingerDown: Boolean,
+    val userNotTrustedOrDetectionIsNeeded: Boolean,
+    ) : KeyguardListenModel()
 /**
  * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock].
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
index 2bd3ca5..db986e0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -103,6 +103,11 @@
         mView.setNextMessageColor(colorState);
     }
 
+    /** Returns the message of the underlying TextView. */
+    public CharSequence getMessage() {
+        return mView.getText();
+    }
+
     /**
      * Reload colors from resources.
      **/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 2bb3a5f..5c4126e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -727,6 +727,11 @@
         mViewMode.reloadColors();
     }
 
+    /** Handles density or font scale changes. */
+    void onDensityOrFontScaleChanged() {
+        mViewMode.onDensityOrFontScaleChanged();
+    }
+
     /**
      * Enscapsulates the differences between bouncer modes for the container.
      */
@@ -752,6 +757,9 @@
         /** Refresh colors */
         default void reloadColors() {};
 
+        /** Handles density or font scale changes. */
+        default void onDensityOrFontScaleChanged() {}
+
         /** On a successful auth, optionally handle how the view disappears */
         default void startDisappearAnimation(SecurityMode securityMode) {};
 
@@ -899,14 +907,9 @@
             mFalsingA11yDelegate = falsingA11yDelegate;
 
             if (mUserSwitcherViewGroup == null) {
-                LayoutInflater.from(v.getContext()).inflate(
-                        R.layout.keyguard_bouncer_user_switcher,
-                        mView,
-                        true);
-                mUserSwitcherViewGroup =  mView.findViewById(R.id.keyguard_bouncer_user_switcher);
+                inflateUserSwitcher();
             }
             updateSecurityViewLocation();
-            mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
             setupUserSwitcher();
             mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
         }
@@ -937,6 +940,12 @@
         }
 
         @Override
+        public void onDensityOrFontScaleChanged() {
+            mView.removeView(mUserSwitcherViewGroup);
+            inflateUserSwitcher();
+        }
+
+        @Override
         public void onDestroy() {
             mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback);
         }
@@ -1097,11 +1106,19 @@
                         new KeyguardSecurityViewTransition());
             }
             int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans);
+            int viewFlipperBottomMargin = mResources.getDimensionPixelSize(
+                    R.dimen.bouncer_user_switcher_view_mode_view_flipper_bottom_margin);
+            int userSwitcherBottomMargin = mResources.getDimensionPixelSize(
+                    R.dimen.bouncer_user_switcher_view_mode_user_switcher_bottom_margin);
             if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                 ConstraintSet constraintSet = new ConstraintSet();
                 constraintSet.connect(mUserSwitcherViewGroup.getId(), TOP, PARENT_ID, TOP, yTrans);
-                constraintSet.connect(mViewFlipper.getId(), TOP, PARENT_ID, TOP);
-                constraintSet.connect(mViewFlipper.getId(), BOTTOM, PARENT_ID, BOTTOM);
+                constraintSet.connect(mUserSwitcherViewGroup.getId(), BOTTOM, mViewFlipper.getId(),
+                        TOP, userSwitcherBottomMargin);
+                constraintSet.connect(mViewFlipper.getId(), TOP, mUserSwitcherViewGroup.getId(),
+                        BOTTOM);
+                constraintSet.connect(mViewFlipper.getId(), BOTTOM, PARENT_ID, BOTTOM,
+                        viewFlipperBottomMargin);
                 constraintSet.centerHorizontally(mViewFlipper.getId(), PARENT_ID);
                 constraintSet.centerHorizontally(mUserSwitcherViewGroup.getId(), PARENT_ID);
                 constraintSet.setVerticalChainStyle(mViewFlipper.getId(), CHAIN_SPREAD);
@@ -1137,6 +1154,15 @@
             }
         }
 
+        private void inflateUserSwitcher() {
+            LayoutInflater.from(mView.getContext()).inflate(
+                    R.layout.keyguard_bouncer_user_switcher,
+                    mView,
+                    true);
+            mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher);
+            mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
+        }
+
         interface UserSwitcherCallback {
             void showUnlockToContinueMessage();
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 7a49926..01be33e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -251,6 +251,11 @@
                 public void onUiModeChanged() {
                     reloadColors();
                 }
+
+                @Override
+                public void onDensityOrFontScaleChanged() {
+                    KeyguardSecurityContainerController.this.onDensityOrFontScaleChanged();
+                }
             };
     private boolean mBouncerVisible = false;
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
@@ -727,6 +732,14 @@
         mView.reloadColors();
     }
 
+    /** Handles density or font scale changes. */
+    private void onDensityOrFontScaleChanged() {
+        mSecurityViewFlipperController.onDensityOrFontScaleChanged();
+        mSecurityViewFlipperController.getSecurityView(mCurrentSecurityMode,
+                mKeyguardSecurityCallback);
+        mView.onDensityOrFontScaleChanged();
+    }
+
     static class Factory {
 
         private final KeyguardSecurityContainer mView;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index bddf4b0..25afe11 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -83,6 +83,13 @@
         }
     }
 
+    /** Handles density or font scale changes. */
+    public void onDensityOrFontScaleChanged() {
+        mView.removeAllViews();
+        mChildren.clear();
+    }
+
+
     @VisibleForTesting
     KeyguardInputViewController<KeyguardInputView> getSecurityView(SecurityMode securityMode,
             KeyguardSecurityCallback keyguardSecurityCallback) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 83e23bd..8b9823b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import android.content.Context;
+import android.os.Trace;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
@@ -112,4 +113,11 @@
             mKeyguardSlice.dump(pw, args);
         }
     }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        Trace.beginSection("KeyguardStatusView#onMeasure");
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        Trace.endSection();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 47ea878..88477aaa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -145,6 +145,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 import com.android.systemui.statusbar.StatusBarState;
@@ -279,6 +280,7 @@
     }
 
     private final Context mContext;
+    private final UserTracker mUserTracker;
     private final KeyguardUpdateMonitorLogger mLogger;
     private final boolean mIsPrimaryUser;
     private final AuthController mAuthController;
@@ -486,21 +488,12 @@
                     FACE_AUTH_TRIGGERED_TRUST_DISABLED);
         }
 
-        mLogger.logTrustChanged(wasTrusted, enabled, userId);
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
-            if (cb != null) {
-                cb.onTrustChanged(userId);
-                if (enabled && flags != 0) {
-                    cb.onTrustGrantedWithFlags(flags, userId);
-                }
-            }
-        }
-
-        if (KeyguardUpdateMonitor.getCurrentUser() == userId) {
-            CharSequence message = null;
-            final boolean userHasTrust = getUserHasTrust(userId);
-            if (userHasTrust && trustGrantedMessages != null) {
+        if (enabled) {
+            String message = null;
+            if (KeyguardUpdateMonitor.getCurrentUser() == userId
+                    && trustGrantedMessages != null) {
+                // Show the first non-empty string provided by a trust agent OR intentionally pass
+                // an empty string through (to prevent the default trust agent string from showing)
                 for (String msg : trustGrantedMessages) {
                     message = msg;
                     if (!TextUtils.isEmpty(message)) {
@@ -509,17 +502,38 @@
                 }
             }
 
-            if (message != null) {
-                mLogger.logShowTrustGrantedMessage(message.toString());
-            }
-            for (int i = 0; i < mCallbacks.size(); i++) {
-                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
-                if (cb != null) {
-                    cb.showTrustGrantedMessage(message);
+            mLogger.logTrustGrantedWithFlags(flags, userId, message);
+            if (userId == getCurrentUser()) {
+                final TrustGrantFlags trustGrantFlags = new TrustGrantFlags(flags);
+                for (int i = 0; i < mCallbacks.size(); i++) {
+                    KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                    if (cb != null) {
+                        cb.onTrustGrantedForCurrentUser(
+                                shouldDismissKeyguardOnTrustGrantedWithCurrentUser(trustGrantFlags),
+                                trustGrantFlags, message);
+                    }
                 }
             }
         }
 
+        mLogger.logTrustChanged(wasTrusted, enabled, userId);
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onTrustChanged(userId);
+            }
+        }
+    }
+
+    /**
+     * Whether the trust granted call with its passed flags should dismiss keyguard.
+     * It's assumed that the trust was granted for the current user.
+     */
+    private boolean shouldDismissKeyguardOnTrustGrantedWithCurrentUser(TrustGrantFlags flags) {
+        final boolean isBouncerShowing = mPrimaryBouncerIsOrWillBeShowing || mUdfpsBouncerShowing;
+        return (flags.isInitiatedByUser() || flags.dismissKeyguardRequested())
+                && (mDeviceInteractive || flags.temporaryAndRenewable())
+                && (isBouncerShowing || flags.dismissKeyguardRequested());
     }
 
     @Override
@@ -796,9 +810,9 @@
         }
         // Don't send cancel if authentication succeeds
         mFingerprintCancelSignal = null;
+        mLogger.logFingerprintSuccess(userId, isStrongBiometric);
         updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
                 FACE_AUTH_UPDATED_FP_AUTHENTICATED);
-        mLogger.logFingerprintSuccess(userId, isStrongBiometric);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -872,13 +886,7 @@
             mHandler.removeCallbacks(mFpCancelNotReceived);
         }
         try {
-            final int userId;
-            try {
-                userId = ActivityManager.getService().getCurrentUser().id;
-            } catch (RemoteException e) {
-                mLogger.logException(e, "Failed to get current user id");
-                return;
-            }
+            final int userId = mUserTracker.getUserId();
             if (userId != authUserId) {
                 mLogger.logFingerprintAuthForWrongUser(authUserId);
                 return;
@@ -1096,13 +1104,7 @@
                 mLogger.d("Aborted successful auth because device is going to sleep.");
                 return;
             }
-            final int userId;
-            try {
-                userId = ActivityManager.getService().getCurrentUser().id;
-            } catch (RemoteException e) {
-                mLogger.logException(e, "Failed to get current user id");
-                return;
-            }
+            final int userId = mUserTracker.getUserId();
             if (userId != authUserId) {
                 mLogger.logFaceAuthForWrongUser(authUserId);
                 return;
@@ -1952,6 +1954,7 @@
     @Inject
     protected KeyguardUpdateMonitor(
             Context context,
+            UserTracker userTracker,
             @Main Looper mainLooper,
             BroadcastDispatcher broadcastDispatcher,
             SecureSettings secureSettings,
@@ -1984,6 +1987,7 @@
             FaceWakeUpTriggersConfig faceWakeUpTriggersConfig) {
         mContext = context;
         mSubscriptionManager = subscriptionManager;
+        mUserTracker = userTracker;
         mTelephonyListenerManager = telephonyListenerManager;
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
         mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged,
@@ -2215,7 +2219,7 @@
 
         TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
         mIsPrimaryUser = mUserManager.isPrimaryUser();
-        int user = ActivityManager.getCurrentUser();
+        int user = mUserTracker.getUserId();
         mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
         updateSecondaryLockscreenRequirement(user);
@@ -2722,9 +2726,9 @@
         final boolean canBypass = mKeyguardBypassController != null
                 && mKeyguardBypassController.canBypass();
         // There's no reason to ask the HAL for authentication when the user can dismiss the
-        // bouncer, unless we're bypassing and need to auto-dismiss the lock screen even when
-        // TrustAgents or biometrics are keeping the device unlocked.
-        final boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;
+        // bouncer because the user is trusted, unless we're bypassing and need to auto-dismiss
+        // the lock screen even when TrustAgents are keeping the device unlocked.
+        final boolean userNotTrustedOrDetectionIsNeeded = !getUserHasTrust(user) || canBypass;
 
         // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
         // Lock-down mode shouldn't scan, since it is more explicit.
@@ -2741,11 +2745,12 @@
             strongAuthAllowsScanning = false;
         }
 
-        // If the face has recently been authenticated do not attempt to authenticate again.
-        final boolean faceAuthenticated = getIsFaceAuthenticated();
+        // If the face or fp has recently been authenticated do not attempt to authenticate again.
+        final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user);
         final boolean faceDisabledForUser = isFaceDisabled(user);
         final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
         final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
+        final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
 
         // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -2755,13 +2760,13 @@
                         || mOccludingAppRequestingFace
                         || awakeKeyguard
                         || shouldListenForFaceAssistant
-                        || mAuthController.isUdfpsFingerDown()
+                        || isUdfpsFingerDown
                         || mUdfpsBouncerShowing)
-                && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer
+                && !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded
                 && !mKeyguardGoingAway && biometricEnabledForUser
                 && strongAuthAllowsScanning && mIsPrimaryUser
                 && (!mSecureCameraLaunched || mOccludingAppRequestingFace)
-                && !faceAuthenticated
+                && faceAndFpNotAuthenticated
                 && !mGoingToSleep
                 // We only care about fp locked out state and not face because we still trigger
                 // face auth even when face is locked out to show the user a message that face
@@ -2775,10 +2780,9 @@
                     user,
                     shouldListen,
                     mAuthInterruptActive,
-                    becauseCannotSkipBouncer,
                     biometricEnabledForUser,
                         mPrimaryBouncerFullyShown,
-                    faceAuthenticated,
+                    faceAndFpNotAuthenticated,
                     faceDisabledForUser,
                     isFaceLockedOut(),
                     fpLockedOut,
@@ -2791,7 +2795,9 @@
                     strongAuthAllowsScanning,
                     mSecureCameraLaunched,
                     mSwitchingUser,
-                    mUdfpsBouncerShowing));
+                    mUdfpsBouncerShowing,
+                    isUdfpsFingerDown,
+                    userNotTrustedOrDetectionIsNeeded));
 
         return shouldListen;
     }
@@ -3841,7 +3847,7 @@
             pw.println("    " + subId + "=" + mServiceStates.get(subId));
         }
         if (mFpm != null && mFpm.isHardwareDetected()) {
-            final int userId = ActivityManager.getCurrentUser();
+            final int userId = mUserTracker.getUserId();
             final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
             BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
             pw.println("  Fingerprint state (user=" + userId + ")");
@@ -3879,7 +3885,7 @@
             }
         }
         if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
-            final int userId = ActivityManager.getCurrentUser();
+            final int userId = mUserTracker.getUserId();
             final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
             BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
             pw.println("  Face authentication state (user=" + userId + ")");
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index c06e1dc..1d58fc9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -19,6 +19,7 @@
 import android.telephony.TelephonyManager;
 import android.view.WindowManagerPolicyConstants;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.fuelgauge.BatteryStatus;
@@ -174,14 +175,14 @@
     public void onTrustManagedChanged(int userId) { }
 
     /**
-     * Called after trust was granted with non-zero flags.
+     * Called after trust was granted.
+     * @param dismissKeyguard whether the keyguard should be dismissed as a result of the
+     *                        trustGranted
+     * @param message optional message the trust agent has provided to show that should indicate
+     *                why trust was granted.
      */
-    public void onTrustGrantedWithFlags(int flags, int userId) { }
-
-    /**
-     * Called when setting the trust granted message.
-     */
-    public void showTrustGrantedMessage(@Nullable CharSequence message) { }
+    public void onTrustGrantedForCurrentUser(boolean dismissKeyguard,
+            @NonNull TrustGrantFlags flags, @Nullable String message) { }
 
     /**
      * Called when a biometric has been acquired.
diff --git a/packages/SystemUI/src/com/android/keyguard/TrustGrantFlags.java b/packages/SystemUI/src/com/android/keyguard/TrustGrantFlags.java
new file mode 100644
index 0000000..d33732c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/TrustGrantFlags.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard;
+
+import android.service.trust.TrustAgentService;
+
+import java.util.Objects;
+
+/**
+ * Translating {@link android.service.trust.TrustAgentService.GrantTrustFlags} to a more
+ * parsable object. These flags are requested by a TrustAgent.
+ */
+public class TrustGrantFlags {
+    final int mFlags;
+
+    public TrustGrantFlags(int flags) {
+        this.mFlags = flags;
+    }
+
+    /** {@link TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER} */
+    public boolean isInitiatedByUser() {
+        return (mFlags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0;
+    }
+
+    /**
+     * Trust agent is requesting to dismiss the keyguard.
+     * See {@link TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD}.
+     *
+     * This does not guarantee that the keyguard is dismissed.
+     * KeyguardUpdateMonitor makes the final determination whether the keyguard should be dismissed.
+     * {@link KeyguardUpdateMonitorCallback#onTrustGrantedForCurrentUser(
+     *      boolean, TrustGrantFlags, String).
+     */
+    public boolean dismissKeyguardRequested() {
+        return (mFlags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0;
+    }
+
+    /** {@link TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE} */
+    public boolean temporaryAndRenewable() {
+        return (mFlags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0;
+    }
+
+    /** {@link TrustAgentService.FLAG_GRANT_TRUST_DISPLAY_MESSAGE} */
+    public boolean displayMessage() {
+        return (mFlags & TrustAgentService.FLAG_GRANT_TRUST_DISPLAY_MESSAGE) != 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof TrustGrantFlags)) {
+            return false;
+        }
+
+        return ((TrustGrantFlags) o).mFlags == this.mFlags;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(mFlags);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        sb.append(mFlags);
+        sb.append("]=");
+
+        if (isInitiatedByUser()) {
+            sb.append("initiatedByUser|");
+        }
+        if (dismissKeyguardRequested()) {
+            sb.append("dismissKeyguard|");
+        }
+        if (temporaryAndRenewable()) {
+            sb.append("temporaryAndRenewable|");
+        }
+        if (displayMessage()) {
+            sb.append("displayMessage|");
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9a0bfc1..ad9609f 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -29,17 +29,17 @@
 import android.util.DisplayMetrics;
 import android.view.LayoutInflater;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.Observer;
 
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManager.DockEventListener;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.settings.CurrentUserObservable;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
 
 import java.util.ArrayList;
@@ -47,6 +47,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
 import javax.inject.Inject;
@@ -69,7 +70,8 @@
     private final ContentResolver mContentResolver;
     private final SettingsWrapper mSettingsWrapper;
     private final Handler mMainHandler = new Handler(Looper.getMainLooper());
-    private final CurrentUserObservable mCurrentUserObservable;
+    private final UserTracker mUserTracker;
+    private final Executor mMainExecutor;
 
     /**
      * Observe settings changes to know when to switch the clock face.
@@ -80,7 +82,7 @@
                 public void onChange(boolean selfChange, Collection<Uri> uris,
                         int flags, int userId) {
                     if (Objects.equals(userId,
-                            mCurrentUserObservable.getCurrentUser().getValue())) {
+                            mUserTracker.getUserId())) {
                         reload();
                     }
                 }
@@ -89,7 +91,13 @@
     /**
      * Observe user changes and react by potentially loading the custom clock for the new user.
      */
-    private final Observer<Integer> mCurrentUserObserver = (newUserId) -> reload();
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    reload();
+                }
+            };
 
     private final PluginManager mPluginManager;
     @Nullable private final DockManager mDockManager;
@@ -129,22 +137,24 @@
     @Inject
     public ClockManager(Context context, LayoutInflater layoutInflater,
             PluginManager pluginManager, SysuiColorExtractor colorExtractor,
-            @Nullable DockManager dockManager, BroadcastDispatcher broadcastDispatcher) {
+            @Nullable DockManager dockManager, UserTracker userTracker,
+            @Main Executor mainExecutor) {
         this(context, layoutInflater, pluginManager, colorExtractor,
-                context.getContentResolver(), new CurrentUserObservable(broadcastDispatcher),
+                context.getContentResolver(), userTracker, mainExecutor,
                 new SettingsWrapper(context.getContentResolver()), dockManager);
     }
 
     @VisibleForTesting
     ClockManager(Context context, LayoutInflater layoutInflater,
             PluginManager pluginManager, SysuiColorExtractor colorExtractor,
-            ContentResolver contentResolver, CurrentUserObservable currentUserObservable,
+            ContentResolver contentResolver, UserTracker userTracker, Executor mainExecutor,
             SettingsWrapper settingsWrapper, DockManager dockManager) {
         mContext = context;
         mPluginManager = pluginManager;
         mContentResolver = contentResolver;
         mSettingsWrapper = settingsWrapper;
-        mCurrentUserObservable = currentUserObservable;
+        mUserTracker = userTracker;
+        mMainExecutor = mainExecutor;
         mDockManager = dockManager;
         mPreviewClocks = new AvailableClocks();
 
@@ -226,7 +236,7 @@
         mContentResolver.registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE),
                 false, mContentObserver, UserHandle.USER_ALL);
-        mCurrentUserObservable.getCurrentUser().observeForever(mCurrentUserObserver);
+        mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
         if (mDockManager != null) {
             mDockManager.addListener(mDockEventListener);
         }
@@ -235,7 +245,7 @@
     private void unregister() {
         mPluginManager.removePluginListener(mPreviewClocks);
         mContentResolver.unregisterContentObserver(mContentObserver);
-        mCurrentUserObservable.getCurrentUser().removeObserver(mCurrentUserObserver);
+        mUserTracker.removeCallback(mUserChangedCallback);
         if (mDockManager != null) {
             mDockManager.removeListener(mDockEventListener);
         }
@@ -363,7 +373,7 @@
             ClockPlugin plugin = null;
             if (ClockManager.this.isDocked()) {
                 final String name = mSettingsWrapper.getDockedClockFace(
-                        mCurrentUserObservable.getCurrentUser().getValue());
+                        mUserTracker.getUserId());
                 if (name != null) {
                     plugin = mClocks.get(name);
                     if (plugin != null) {
@@ -372,7 +382,7 @@
                 }
             }
             final String name = mSettingsWrapper.getLockScreenCustomClockFace(
-                    mCurrentUserObservable.getCurrentUser().getValue());
+                    mUserTracker.getUserId());
             if (name != null) {
                 plugin = mClocks.get(name);
             }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
index 32ce537..9e58500 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
@@ -18,14 +18,11 @@
 
 import com.android.systemui.log.dagger.KeyguardLog
 import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
 import com.android.systemui.plugins.log.LogLevel.DEBUG
 import com.android.systemui.plugins.log.LogLevel.ERROR
 import com.android.systemui.plugins.log.LogLevel.INFO
 import com.android.systemui.plugins.log.LogLevel.VERBOSE
 import com.android.systemui.plugins.log.LogLevel.WARNING
-import com.android.systemui.plugins.log.MessageInitializer
-import com.android.systemui.plugins.log.MessagePrinter
 import com.google.errorprone.annotations.CompileTimeConstant
 import javax.inject.Inject
 
@@ -37,18 +34,16 @@
  * an overkill.
  */
 class KeyguardLogger @Inject constructor(@KeyguardLog private val buffer: LogBuffer) {
-    fun d(@CompileTimeConstant msg: String) = log(msg, DEBUG)
+    fun d(@CompileTimeConstant msg: String) = buffer.log(TAG, DEBUG, msg)
 
-    fun e(@CompileTimeConstant msg: String) = log(msg, ERROR)
+    fun e(@CompileTimeConstant msg: String) = buffer.log(TAG, ERROR, msg)
 
-    fun v(@CompileTimeConstant msg: String) = log(msg, VERBOSE)
+    fun v(@CompileTimeConstant msg: String) = buffer.log(TAG, VERBOSE, msg)
 
-    fun w(@CompileTimeConstant msg: String) = log(msg, WARNING)
+    fun w(@CompileTimeConstant msg: String) = buffer.log(TAG, WARNING, msg)
 
-    fun log(msg: String, level: LogLevel) = buffer.log(TAG, level, msg)
-
-    private fun debugLog(messageInitializer: MessageInitializer, messagePrinter: MessagePrinter) {
-        buffer.log(TAG, DEBUG, messageInitializer, messagePrinter)
+    fun logException(ex: Exception, @CompileTimeConstant logMsg: String) {
+        buffer.log(TAG, ERROR, {}, { logMsg }, exception = ex)
     }
 
     fun v(msg: String, arg: Any) {
@@ -61,17 +56,24 @@
 
     // TODO: remove after b/237743330 is fixed
     fun logStatusBarCalculatedAlpha(alpha: Float) {
-        debugLog({ double1 = alpha.toDouble() }, { "Calculated new alpha: $double1" })
+        buffer.log(TAG, DEBUG, { double1 = alpha.toDouble() }, { "Calculated new alpha: $double1" })
     }
 
     // TODO: remove after b/237743330 is fixed
     fun logStatusBarExplicitAlpha(alpha: Float) {
-        debugLog({ double1 = alpha.toDouble() }, { "new mExplicitAlpha value: $double1" })
+        buffer.log(
+            TAG,
+            DEBUG,
+            { double1 = alpha.toDouble() },
+            { "new mExplicitAlpha value: $double1" }
+        )
     }
 
     // TODO: remove after b/237743330 is fixed
     fun logStatusBarAlphaVisibility(visibility: Int, alpha: Float, state: String) {
-        debugLog(
+        buffer.log(
+            TAG,
+            DEBUG,
             {
                 int1 = visibility
                 double1 = alpha.toDouble()
@@ -80,4 +82,22 @@
             { "changing visibility to $int1 with alpha $double1 in state: $str1" }
         )
     }
+
+    @JvmOverloads
+    fun logBiometricMessage(
+        @CompileTimeConstant context: String,
+        msgId: Int? = null,
+        msg: String? = null
+    ) {
+        buffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = context
+                str2 = "$msgId"
+                str3 = msg
+            },
+            { "$str1 msgId: $str2 msg: $str3" }
+        )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 81b8dfe..6763700 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -25,6 +25,7 @@
 import com.android.keyguard.FaceAuthUiEvent
 import com.android.keyguard.KeyguardListenModel
 import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.keyguard.TrustGrantFlags
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel
 import com.android.systemui.plugins.log.LogLevel.DEBUG
@@ -368,12 +369,16 @@
                 }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" })
     }
 
-    fun logShowTrustGrantedMessage(
+    fun logTrustGrantedWithFlags(
+            flags: Int,
+            userId: Int,
             message: String?
     ) {
         logBuffer.log(TAG, DEBUG, {
+            int1 = flags
+            int2 = userId
             str1 = message
-        }, { "showTrustGrantedMessage message$str1" })
+        }, { "trustGrantedWithFlags[user=$int2] flags=${TrustGrantFlags(int1)} message=$str1" })
     }
 
     fun logTrustChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index a5fdc68..51bcd6b 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -70,6 +70,7 @@
 import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -357,6 +358,7 @@
     @Inject Lazy<GroupExpansionManager> mGroupExpansionManagerLazy;
     @Inject Lazy<SystemUIDialogManager> mSystemUIDialogManagerLazy;
     @Inject Lazy<DialogLaunchAnimator> mDialogLaunchAnimatorLazy;
+    @Inject Lazy<UserTracker> mUserTrackerLazy;
 
     @Inject
     public Dependency() {
@@ -564,6 +566,7 @@
         mProviders.put(GroupExpansionManager.class, mGroupExpansionManagerLazy::get);
         mProviders.put(SystemUIDialogManager.class, mSystemUIDialogManagerLazy::get);
         mProviders.put(DialogLaunchAnimator.class, mDialogLaunchAnimatorLazy::get);
+        mProviders.put(UserTracker.class, mUserTrackerLazy::get);
 
         Dependency.setInstance(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index 5d52056..90ecb46 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -169,7 +169,7 @@
             return
         }
         cutoutPath.reset()
-        display.getDisplayInfo(displayInfo)
+        context.display?.getDisplayInfo(displayInfo)
         displayInfo.displayCutout?.cutoutPath?.let { path -> cutoutPath.set(path) }
         invalidate()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 11d579d..7e3b1389 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -26,7 +26,6 @@
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -170,6 +169,7 @@
     private Display.Mode mDisplayMode;
     @VisibleForTesting
     protected DisplayInfo mDisplayInfo = new DisplayInfo();
+    private DisplayCutout mDisplayCutout;
 
     @VisibleForTesting
     protected void showCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) {
@@ -384,6 +384,7 @@
         mRotation = mDisplayInfo.rotation;
         mDisplayMode = mDisplayInfo.getMode();
         mDisplayUniqueId = mDisplayInfo.uniqueId;
+        mDisplayCutout = mDisplayInfo.displayCutout;
         mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
                 mDisplayUniqueId);
         mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
@@ -899,7 +900,7 @@
     private final BroadcastReceiver mUserSwitchIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            int newUserId = ActivityManager.getCurrentUser();
+            int newUserId = mUserTracker.getUserId();
             if (DEBUG) {
                 Log.d(TAG, "UserSwitched newUserId=" + newUserId);
             }
@@ -1022,7 +1023,8 @@
         mRoundedCornerResDelegate.dump(pw, args);
     }
 
-    private void updateConfiguration() {
+    @VisibleForTesting
+    void updateConfiguration() {
         Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
                 "must call on " + mHandler.getLooper().getThread()
                         + ", but was " + Thread.currentThread());
@@ -1033,11 +1035,14 @@
             mDotViewController.setNewRotation(newRotation);
         }
         final Display.Mode newMod = mDisplayInfo.getMode();
+        final DisplayCutout newCutout = mDisplayInfo.displayCutout;
 
         if (!mPendingConfigChange
-                && (newRotation != mRotation || displayModeChanged(mDisplayMode, newMod))) {
+                && (newRotation != mRotation || displayModeChanged(mDisplayMode, newMod)
+                || !Objects.equals(newCutout, mDisplayCutout))) {
             mRotation = newRotation;
             mDisplayMode = newMod;
+            mDisplayCutout = newCutout;
             mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
                     getPhysicalPixelDisplaySizeRatio());
             if (mScreenDecorHwcLayer != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 9f1c9b4..998288a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -291,8 +291,11 @@
         mA11yManager.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK);
         mA11yManager.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME);
         mA11yManager.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS);
-        mA11yManager.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
-        mA11yManager.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+        if (mCentralSurfacesOptionalLazy.get().isPresent()) {
+            // These two actions require the CentralSurfaces instance.
+            mA11yManager.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
+            mA11yManager.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+        }
         mA11yManager.registerSystemAction(actionPowerDialog, SYSTEM_ACTION_ID_POWER_DIALOG);
         mA11yManager.registerSystemAction(actionLockScreen, SYSTEM_ACTION_ID_LOCK_SCREEN);
         mA11yManager.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt b/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt
new file mode 100644
index 0000000..b52ddc1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.battery
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.ColorFilter
+import android.graphics.Matrix
+import android.graphics.Paint
+import android.graphics.Path
+import android.graphics.PixelFormat
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffXfermode
+import android.graphics.Rect
+import android.graphics.drawable.DrawableWrapper
+import android.util.PathParser
+import com.android.settingslib.graph.ThemedBatteryDrawable
+import com.android.systemui.R
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
+import com.android.systemui.battery.BatterySpecs.SHIELD_LEFT_OFFSET
+import com.android.systemui.battery.BatterySpecs.SHIELD_STROKE
+import com.android.systemui.battery.BatterySpecs.SHIELD_TOP_OFFSET
+
+/**
+ * A battery drawable that accessorizes [ThemedBatteryDrawable] with additional information if
+ * necessary.
+ *
+ * For now, it adds a shield in the bottom-right corner when [displayShield] is true.
+ */
+class AccessorizedBatteryDrawable(
+    private val context: Context,
+    frameColor: Int,
+) : DrawableWrapper(ThemedBatteryDrawable(context, frameColor)) {
+    private val mainBatteryDrawable: ThemedBatteryDrawable
+        get() = drawable as ThemedBatteryDrawable
+
+    private val shieldPath = Path()
+    private val scaledShield = Path()
+    private val scaleMatrix = Matrix()
+
+    private var shieldLeftOffsetScaled = SHIELD_LEFT_OFFSET
+    private var shieldTopOffsetScaled = SHIELD_TOP_OFFSET
+
+    private var density = context.resources.displayMetrics.density
+
+    private val dualTone =
+        context.resources.getBoolean(com.android.internal.R.bool.config_batterymeterDualTone)
+
+    private val shieldTransparentOutlinePaint =
+        Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+            p.color = Color.TRANSPARENT
+            p.strokeWidth = ThemedBatteryDrawable.PROTECTION_MIN_STROKE_WIDTH
+            p.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
+            p.style = Paint.Style.FILL_AND_STROKE
+        }
+
+    private val shieldPaint =
+        Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+            p.color = Color.MAGENTA
+            p.style = Paint.Style.FILL
+            p.isDither = true
+        }
+
+    init {
+        loadPaths()
+    }
+
+    override fun onBoundsChange(bounds: Rect) {
+        super.onBoundsChange(bounds)
+        updateSizes()
+    }
+
+    var displayShield: Boolean = false
+
+    private fun updateSizes() {
+        val b = bounds
+        if (b.isEmpty) {
+            return
+        }
+
+        val mainWidth = BatterySpecs.getMainBatteryWidth(b.width().toFloat(), displayShield)
+        val mainHeight = BatterySpecs.getMainBatteryHeight(b.height().toFloat(), displayShield)
+
+        drawable?.setBounds(
+            b.left,
+            b.top,
+            /* right= */ b.left + mainWidth.toInt(),
+            /* bottom= */ b.top + mainHeight.toInt()
+        )
+
+        if (displayShield) {
+            val sx = b.right / BATTERY_WIDTH_WITH_SHIELD
+            val sy = b.bottom / BATTERY_HEIGHT_WITH_SHIELD
+            scaleMatrix.setScale(sx, sy)
+            shieldPath.transform(scaleMatrix, scaledShield)
+
+            shieldLeftOffsetScaled = sx * SHIELD_LEFT_OFFSET
+            shieldTopOffsetScaled = sy * SHIELD_TOP_OFFSET
+
+            val scaledStrokeWidth =
+                (sx * SHIELD_STROKE).coerceAtLeast(
+                    ThemedBatteryDrawable.PROTECTION_MIN_STROKE_WIDTH
+                )
+            shieldTransparentOutlinePaint.strokeWidth = scaledStrokeWidth
+        }
+    }
+
+    override fun getIntrinsicHeight(): Int {
+        val height =
+            if (displayShield) {
+                BATTERY_HEIGHT_WITH_SHIELD
+            } else {
+                BATTERY_HEIGHT
+            }
+        return (height * density).toInt()
+    }
+
+    override fun getIntrinsicWidth(): Int {
+        val width =
+            if (displayShield) {
+                BATTERY_WIDTH_WITH_SHIELD
+            } else {
+                BATTERY_WIDTH
+            }
+        return (width * density).toInt()
+    }
+
+    override fun draw(c: Canvas) {
+        c.saveLayer(null, null)
+        // Draw the main battery icon
+        super.draw(c)
+
+        if (displayShield) {
+            c.translate(shieldLeftOffsetScaled, shieldTopOffsetScaled)
+            // We need a transparent outline around the shield, so first draw the transparent-ness
+            // then draw the shield
+            c.drawPath(scaledShield, shieldTransparentOutlinePaint)
+            c.drawPath(scaledShield, shieldPaint)
+        }
+        c.restore()
+    }
+
+    override fun getOpacity(): Int {
+        return PixelFormat.OPAQUE
+    }
+
+    override fun setAlpha(p0: Int) {
+        // Unused internally -- see [ThemedBatteryDrawable.setAlpha].
+    }
+
+    override fun setColorFilter(colorfilter: ColorFilter?) {
+        super.setColorFilter(colorFilter)
+        shieldPaint.colorFilter = colorFilter
+    }
+
+    /** Sets whether the battery is currently charging. */
+    fun setCharging(charging: Boolean) {
+        mainBatteryDrawable.charging = charging
+    }
+
+    /** Sets the current level (out of 100) of the battery. */
+    fun setBatteryLevel(level: Int) {
+        mainBatteryDrawable.setBatteryLevel(level)
+    }
+
+    /** Sets whether power save is enabled. */
+    fun setPowerSaveEnabled(powerSaveEnabled: Boolean) {
+        mainBatteryDrawable.powerSaveEnabled = powerSaveEnabled
+    }
+
+    /** Returns whether power save is currently enabled. */
+    fun getPowerSaveEnabled(): Boolean {
+        return mainBatteryDrawable.powerSaveEnabled
+    }
+
+    /** Sets the colors to use for the icon. */
+    fun setColors(fgColor: Int, bgColor: Int, singleToneColor: Int) {
+        shieldPaint.color = if (dualTone) fgColor else singleToneColor
+        mainBatteryDrawable.setColors(fgColor, bgColor, singleToneColor)
+    }
+
+    /** Notifies this drawable that the density might have changed. */
+    fun notifyDensityChanged() {
+        density = context.resources.displayMetrics.density
+    }
+
+    private fun loadPaths() {
+        val shieldPathString = context.resources.getString(R.string.config_batterymeterShieldPath)
+        shieldPath.set(PathParser.createPathFromPathData(shieldPathString))
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 6a10d4a..03d999f 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -45,7 +45,6 @@
 import androidx.annotation.StyleRes;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.settingslib.graph.ThemedBatteryDrawable;
 import com.android.systemui.DualToneHandler;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
@@ -68,7 +67,7 @@
     public static final int MODE_OFF = 2;
     public static final int MODE_ESTIMATE = 3;
 
-    private final ThemedBatteryDrawable mDrawable;
+    private final AccessorizedBatteryDrawable mDrawable;
     private final ImageView mBatteryIconView;
     private TextView mBatteryPercentView;
 
@@ -77,7 +76,10 @@
     private int mLevel;
     private int mShowPercentMode = MODE_DEFAULT;
     private boolean mShowPercentAvailable;
+    private String mEstimateText = null;
     private boolean mCharging;
+    private boolean mIsOverheated;
+    private boolean mDisplayShieldEnabled;
     // Error state where we know nothing about the current battery state
     private boolean mBatteryStateUnknown;
     // Lazily-loaded since this is expected to be a rare-if-ever state
@@ -106,7 +108,7 @@
         final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
                 context.getColor(R.color.meter_background_color));
         mPercentageStyleId = atts.getResourceId(R.styleable.BatteryMeterView_textAppearance, 0);
-        mDrawable = new ThemedBatteryDrawable(context, frameColor);
+        mDrawable = new AccessorizedBatteryDrawable(context, frameColor);
         atts.recycle();
 
         mShowPercentAvailable = context.getResources().getBoolean(
@@ -170,12 +172,14 @@
         if (mode == mShowPercentMode) return;
         mShowPercentMode = mode;
         updateShowPercent();
+        updatePercentText();
     }
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         updatePercentView();
+        mDrawable.notifyDensityChanged();
     }
 
     public void setColorsFromContext(Context context) {
@@ -203,6 +207,17 @@
         mDrawable.setPowerSaveEnabled(isPowerSave);
     }
 
+    void onIsOverheatedChanged(boolean isOverheated) {
+        boolean valueChanged = mIsOverheated != isOverheated;
+        mIsOverheated = isOverheated;
+        if (valueChanged) {
+            updateContentDescription();
+            // The battery drawable is a different size depending on whether it's currently
+            // overheated or not, so we need to re-scale the view when overheated changes.
+            scaleBatteryMeterViews();
+        }
+    }
+
     private TextView loadPercentView() {
         return (TextView) LayoutInflater.from(getContext())
                 .inflate(R.layout.battery_percentage_view, null);
@@ -227,13 +242,17 @@
         mBatteryEstimateFetcher = fetcher;
     }
 
+    void setDisplayShieldEnabled(boolean displayShieldEnabled) {
+        mDisplayShieldEnabled = displayShieldEnabled;
+    }
+
     void updatePercentText() {
         if (mBatteryStateUnknown) {
-            setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
             return;
         }
 
         if (mBatteryEstimateFetcher == null) {
+            setPercentTextAtCurrentLevel();
             return;
         }
 
@@ -245,10 +264,9 @@
                         return;
                     }
                     if (estimate != null && mShowPercentMode == MODE_ESTIMATE) {
+                        mEstimateText = estimate;
                         mBatteryPercentView.setText(estimate);
-                        setContentDescription(getContext().getString(
-                                R.string.accessibility_battery_level_with_estimate,
-                                mLevel, estimate));
+                        updateContentDescription();
                     } else {
                         setPercentTextAtCurrentLevel();
                     }
@@ -257,28 +275,49 @@
                 setPercentTextAtCurrentLevel();
             }
         } else {
-            setContentDescription(
-                    getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
-                            : R.string.accessibility_battery_level, mLevel));
+            updateContentDescription();
         }
     }
 
     private void setPercentTextAtCurrentLevel() {
-        if (mBatteryPercentView == null) {
-            return;
+        if (mBatteryPercentView != null) {
+            mEstimateText = null;
+            String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
+            // Setting text actually triggers a layout pass (because the text view is set to
+            // wrap_content width and TextView always relayouts for this). Avoid needless
+            // relayout if the text didn't actually change.
+            if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
+                mBatteryPercentView.setText(percentText);
+            }
         }
 
-        String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
-        // Setting text actually triggers a layout pass (because the text view is set to
-        // wrap_content width and TextView always relayouts for this). Avoid needless
-        // relayout if the text didn't actually change.
-        if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
-            mBatteryPercentView.setText(percentText);
+        updateContentDescription();
+    }
+
+    private void updateContentDescription() {
+        Context context = getContext();
+
+        String contentDescription;
+        if (mBatteryStateUnknown) {
+            contentDescription = context.getString(R.string.accessibility_battery_unknown);
+        } else if (mShowPercentMode == MODE_ESTIMATE && !TextUtils.isEmpty(mEstimateText)) {
+            contentDescription = context.getString(
+                    mIsOverheated
+                            ? R.string.accessibility_battery_level_charging_paused_with_estimate
+                            : R.string.accessibility_battery_level_with_estimate,
+                    mLevel,
+                    mEstimateText);
+        } else if (mIsOverheated) {
+            contentDescription =
+                    context.getString(R.string.accessibility_battery_level_charging_paused, mLevel);
+        } else if (mCharging) {
+            contentDescription =
+                    context.getString(R.string.accessibility_battery_level_charging, mLevel);
+        } else {
+            contentDescription = context.getString(R.string.accessibility_battery_level, mLevel);
         }
 
-        setContentDescription(
-                getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
-                        : R.string.accessibility_battery_level, mLevel));
+        setContentDescription(contentDescription);
     }
 
     void updateShowPercent() {
@@ -329,6 +368,7 @@
         }
 
         mBatteryStateUnknown = isUnknown;
+        updateContentDescription();
 
         if (mBatteryStateUnknown) {
             mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
@@ -349,15 +389,43 @@
         res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
         float iconScaleFactor = typedValue.getFloat();
 
-        int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
-        int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
+        float mainBatteryHeight =
+                res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height) * iconScaleFactor;
+        float mainBatteryWidth =
+                res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width) * iconScaleFactor;
+
+        // If the battery is marked as overheated, we should display a shield indicating that the
+        // battery is being "defended".
+        boolean displayShield = mDisplayShieldEnabled && mIsOverheated;
+        float fullBatteryIconHeight =
+                BatterySpecs.getFullBatteryHeight(mainBatteryHeight, displayShield);
+        float fullBatteryIconWidth =
+                BatterySpecs.getFullBatteryWidth(mainBatteryWidth, displayShield);
+
+        int marginTop;
+        if (displayShield) {
+            // If the shield is displayed, we need some extra marginTop so that the bottom of the
+            // main icon is still aligned with the bottom of all the other system icons.
+            int shieldHeightAddition = Math.round(fullBatteryIconHeight - mainBatteryHeight);
+            // However, the other system icons have some embedded bottom padding that the battery
+            // doesn't have, so we shouldn't move the battery icon down by the full amount.
+            // See b/258672854.
+            marginTop = shieldHeightAddition
+                    - res.getDimensionPixelSize(R.dimen.status_bar_battery_extra_vertical_spacing);
+        } else {
+            marginTop = 0;
+        }
+
         int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
 
         LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
-                (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
-        scaledLayoutParams.setMargins(0, 0, 0, marginBottom);
+                Math.round(fullBatteryIconWidth),
+                Math.round(fullBatteryIconHeight));
+        scaledLayoutParams.setMargins(0, marginTop, 0, marginBottom);
 
+        mDrawable.setDisplayShield(displayShield);
         mBatteryIconView.setLayoutParams(scaledLayoutParams);
+        mBatteryIconView.invalidateDrawable(mDrawable);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index ae9a323..f4ec33a 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -17,19 +17,23 @@
 
 import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
-import android.app.ActivityManager;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.view.View;
 
-import com.android.systemui.broadcast.BroadcastDispatcher;
+import androidx.annotation.NonNull;
+
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -42,12 +46,13 @@
 public class BatteryMeterViewController extends ViewController<BatteryMeterView> {
     private final ConfigurationController mConfigurationController;
     private final TunerService mTunerService;
+    private final Handler mMainHandler;
     private final ContentResolver mContentResolver;
     private final BatteryController mBatteryController;
 
     private final String mSlotBattery;
     private final SettingObserver mSettingObserver;
-    private final CurrentUserTracker mCurrentUserTracker;
+    private final UserTracker mUserTracker;
 
     private final ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
@@ -84,6 +89,21 @@
                 public void onBatteryUnknownStateChanged(boolean isUnknown) {
                     mView.onBatteryUnknownStateChanged(isUnknown);
                 }
+
+                @Override
+                public void onIsOverheatedChanged(boolean isOverheated) {
+                    mView.onIsOverheatedChanged(isOverheated);
+                }
+            };
+
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    mContentResolver.unregisterContentObserver(mSettingObserver);
+                    registerShowBatteryPercentObserver(newUser);
+                    mView.updateShowPercent();
+                }
             };
 
     // Some places may need to show the battery conditionally, and not obey the tuner
@@ -93,30 +113,26 @@
     @Inject
     public BatteryMeterViewController(
             BatteryMeterView view,
+            UserTracker userTracker,
             ConfigurationController configurationController,
             TunerService tunerService,
-            BroadcastDispatcher broadcastDispatcher,
             @Main Handler mainHandler,
             ContentResolver contentResolver,
+            FeatureFlags featureFlags,
             BatteryController batteryController) {
         super(view);
+        mUserTracker = userTracker;
         mConfigurationController = configurationController;
         mTunerService = tunerService;
+        mMainHandler = mainHandler;
         mContentResolver = contentResolver;
         mBatteryController = batteryController;
 
         mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
+        mView.setDisplayShieldEnabled(featureFlags.isEnabled(Flags.BATTERY_SHIELD_ICON));
 
         mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
-        mSettingObserver = new SettingObserver(mainHandler);
-        mCurrentUserTracker = new CurrentUserTracker(broadcastDispatcher) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                contentResolver.unregisterContentObserver(mSettingObserver);
-                registerShowBatteryPercentObserver(newUserId);
-                mView.updateShowPercent();
-            }
-        };
+        mSettingObserver = new SettingObserver(mMainHandler);
     }
 
     @Override
@@ -125,9 +141,9 @@
         subscribeForTunerUpdates();
         mBatteryController.addCallback(mBatteryStateChangeCallback);
 
-        registerShowBatteryPercentObserver(ActivityManager.getCurrentUser());
+        registerShowBatteryPercentObserver(mUserTracker.getUserId());
         registerGlobalBatteryUpdateObserver();
-        mCurrentUserTracker.startTracking();
+        mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(mMainHandler));
 
         mView.updateShowPercent();
     }
@@ -138,7 +154,7 @@
         unsubscribeFromTunerUpdates();
         mBatteryController.removeCallback(mBatteryStateChangeCallback);
 
-        mCurrentUserTracker.stopTracking();
+        mUserTracker.removeCallback(mUserChangedCallback);
         mContentResolver.unregisterContentObserver(mSettingObserver);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatterySpecs.kt b/packages/SystemUI/src/com/android/systemui/battery/BatterySpecs.kt
new file mode 100644
index 0000000..6455a96
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatterySpecs.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.battery
+
+import com.android.settingslib.graph.ThemedBatteryDrawable
+
+/** An object storing specs related to the battery icon in the status bar. */
+object BatterySpecs {
+
+    /** Width of the main battery icon, not including the shield. */
+    const val BATTERY_WIDTH = ThemedBatteryDrawable.WIDTH
+    /** Height of the main battery icon, not including the shield. */
+    const val BATTERY_HEIGHT = ThemedBatteryDrawable.HEIGHT
+
+    private const val SHIELD_WIDTH = 10f
+    private const val SHIELD_HEIGHT = 13f
+
+    /**
+     * Amount that the left side of the shield should be offset from the left side of the battery.
+     */
+    const val SHIELD_LEFT_OFFSET = 8f
+    /** Amount that the top of the shield should be offset from the top of the battery. */
+    const val SHIELD_TOP_OFFSET = 10f
+
+    const val SHIELD_STROKE = 4f
+
+    /** The full width of the battery icon, including the main battery icon *and* the shield. */
+    const val BATTERY_WIDTH_WITH_SHIELD = SHIELD_LEFT_OFFSET + SHIELD_WIDTH
+    /** The full height of the battery icon, including the main battery icon *and* the shield. */
+    const val BATTERY_HEIGHT_WITH_SHIELD = SHIELD_TOP_OFFSET + SHIELD_HEIGHT
+
+    /**
+     * Given the desired height of the main battery icon in pixels, returns the height that the full
+     * battery icon will take up in pixels.
+     *
+     * If there's no shield, this will just return [mainBatteryHeight]. Otherwise, the shield
+     * extends slightly below the bottom of the main battery icon so we need some extra height.
+     */
+    @JvmStatic
+    fun getFullBatteryHeight(mainBatteryHeight: Float, displayShield: Boolean): Float {
+        return if (!displayShield) {
+            mainBatteryHeight
+        } else {
+            val verticalScaleFactor = mainBatteryHeight / BATTERY_HEIGHT
+            verticalScaleFactor * BATTERY_HEIGHT_WITH_SHIELD
+        }
+    }
+
+    /**
+     * Given the desired width of the main battery icon in pixels, returns the width that the full
+     * battery icon will take up in pixels.
+     *
+     * If there's no shield, this will just return [mainBatteryWidth]. Otherwise, the shield extends
+     * past the right side of the main battery icon so we need some extra width.
+     */
+    @JvmStatic
+    fun getFullBatteryWidth(mainBatteryWidth: Float, displayShield: Boolean): Float {
+        return if (!displayShield) {
+            mainBatteryWidth
+        } else {
+            val horizontalScaleFactor = mainBatteryWidth / BATTERY_WIDTH
+            horizontalScaleFactor * BATTERY_WIDTH_WITH_SHIELD
+        }
+    }
+
+    /**
+     * Given the height of the full battery icon, return how tall the main battery icon should be.
+     *
+     * If there's no shield, this will just return [fullBatteryHeight]. Otherwise, the shield takes
+     * up some of the view's height so the main battery width will be just a portion of
+     * [fullBatteryHeight].
+     */
+    @JvmStatic
+    fun getMainBatteryHeight(fullBatteryHeight: Float, displayShield: Boolean): Float {
+        return if (!displayShield) {
+            fullBatteryHeight
+        } else {
+            return (BATTERY_HEIGHT / BATTERY_HEIGHT_WITH_SHIELD) * fullBatteryHeight
+        }
+    }
+
+    /**
+     * Given the width of the full battery icon, return how wide the main battery icon should be.
+     *
+     * If there's no shield, this will just return [fullBatteryWidth]. Otherwise, the shield takes
+     * up some of the view's width so the main battery width will be just a portion of
+     * [fullBatteryWidth].
+     */
+    @JvmStatic
+    fun getMainBatteryWidth(fullBatteryWidth: Float, displayShield: Boolean): Float {
+        return if (!displayShield) {
+            fullBatteryWidth
+        } else {
+            return (BATTERY_WIDTH / BATTERY_WIDTH_WITH_SHIELD) * fullBatteryWidth
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index c93fe6a..4b57d45 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -29,7 +29,7 @@
 import android.view.animation.PathInterpolator
 import com.android.internal.graphics.ColorUtils
 import com.android.systemui.animation.Interpolators
-import com.android.systemui.ripple.RippleShader
+import com.android.systemui.surfaceeffects.ripple.RippleShader
 
 private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
index ad96612..bdad413 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
@@ -37,6 +37,9 @@
     private float mDialogSuggestedAlpha = 1f;
     private float mNotificationShadeExpansion = 0f;
 
+    // Used for Udfps ellipse detection when flag is true, set by AnimationViewController
+    boolean mUseExpandedOverlay = false;
+
     // mAlpha takes into consideration the status bar expansion amount and dialog suggested alpha
     private int mAlpha;
     boolean mPauseAuth;
@@ -118,6 +121,24 @@
     }
 
     /**
+     * Converts coordinates of RectF relative to the screen to coordinates relative to this view.
+     *
+     * @param bounds RectF based off screen coordinates in current orientation
+     */
+    RectF getBoundsRelativeToView(RectF bounds) {
+        int[] pos = getLocationOnScreen();
+
+        RectF output = new RectF(
+                bounds.left - pos[0],
+                bounds.top - pos[1],
+                bounds.right - pos[0],
+                bounds.bottom - pos[1]
+        );
+
+        return output;
+    }
+
+    /**
      * Set the suggested alpha based on whether a dialog was recently shown or hidden.
      * @param dialogSuggestedAlpha value from 0f to 1f.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index bc10868..45595c8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -66,6 +66,7 @@
 import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.plugins.FalsingManager;
@@ -149,7 +150,7 @@
     // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
     @Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
     @Nullable private final AlternateUdfpsTouchProvider mAlternateTouchProvider;
-    @Nullable private UdfpsDisplayMode mUdfpsDisplayMode;
+    @Nullable private UdfpsDisplayModeProvider mUdfpsDisplayMode;
 
     // Tracks the velocity of a touch to help filter out the touches that move too fast.
     @Nullable private VelocityTracker mVelocityTracker;
@@ -164,6 +165,7 @@
 
     // The current request from FingerprintService. Null if no current request.
     @Nullable UdfpsControllerOverlay mOverlay;
+    @Nullable private UdfpsEllipseDetection mUdfpsEllipseDetection;
 
     // The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
     // to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -320,6 +322,10 @@
         if (!mOverlayParams.equals(overlayParams)) {
             mOverlayParams = overlayParams;
 
+            if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
+                mUdfpsEllipseDetection.updateOverlayParams(overlayParams);
+            }
+
             final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer();
 
             // When the bounds change it's always necessary to re-create the overlay's window with
@@ -459,8 +465,23 @@
                     mVelocityTracker.clear();
                 }
 
-                boolean withinSensorArea =
+                boolean withinSensorArea;
+                if (mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+                    if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
+                        // Ellipse detection
+                        withinSensorArea = mUdfpsEllipseDetection.isGoodEllipseOverlap(event);
+                    } else {
+                        // Centroid with expanded overlay
+                        withinSensorArea =
+                            isWithinSensorArea(udfpsView, event.getRawX(),
+                                        event.getRawY(), fromUdfpsView);
+                    }
+                } else {
+                    // Centroid with sensor sized view
+                    withinSensorArea =
                         isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView);
+                }
+
                 if (withinSensorArea) {
                     Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0);
                     Log.v(TAG, "onTouch | action down");
@@ -491,9 +512,25 @@
                         ? event.getPointerId(0)
                         : event.findPointerIndex(mActivePointerId);
                 if (idx == event.getActionIndex()) {
-                    boolean actionMoveWithinSensorArea =
-                            isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
-                                    fromUdfpsView);
+                    boolean actionMoveWithinSensorArea;
+                    if (mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+                        if (mFeatureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
+                            // Ellipse detection
+                            actionMoveWithinSensorArea =
+                                    mUdfpsEllipseDetection.isGoodEllipseOverlap(event);
+                        } else {
+                            // Centroid with expanded overlay
+                            actionMoveWithinSensorArea =
+                                isWithinSensorArea(udfpsView, event.getRawX(idx),
+                                        event.getRawY(idx), fromUdfpsView);
+                        }
+                    } else {
+                        // Centroid with sensor sized view
+                        actionMoveWithinSensorArea =
+                            isWithinSensorArea(udfpsView, event.getX(idx),
+                                    event.getY(idx), fromUdfpsView);
+                    }
+
                     if ((fromUdfpsView || actionMoveWithinSensorArea)
                             && shouldTryToDismissKeyguard()) {
                         Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
@@ -691,6 +728,10 @@
 
         udfpsHapticsSimulator.setUdfpsController(this);
         udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController);
+
+        if (featureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
+            mUdfpsEllipseDetection = new UdfpsEllipseDetection(mOverlayParams);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 0bb24f8..8db4927 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -49,6 +49,7 @@
 import com.android.systemui.animation.ActivityLaunchAnimator
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionStateManager
@@ -103,6 +104,7 @@
         private set
 
     private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams()
+    private var sensorBounds: Rect = Rect()
 
     private var overlayTouchListener: TouchExplorationStateChangeListener? = null
 
@@ -120,6 +122,10 @@
         privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
         // Avoid announcing window title.
         accessibilityTitle = " "
+
+        if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+            inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_SPY
+        }
     }
 
     /** A helper if the [requestReason] was due to enrollment. */
@@ -160,6 +166,7 @@
     fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean {
         if (overlayView == null) {
             overlayParams = params
+            sensorBounds = Rect(params.sensorBounds)
             try {
                 overlayView = (inflater.inflate(
                     R.layout.udfps_view, null, false
@@ -178,6 +185,7 @@
                     }
 
                     windowManager.addView(this, coreLayoutParams.updateDimensions(animation))
+                    sensorRect = sensorBounds
                     touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled
                     overlayTouchListener = TouchExplorationStateChangeListener {
                         if (accessibilityManager.isTouchExplorationEnabled) {
@@ -194,6 +202,7 @@
                         overlayTouchListener!!
                     )
                     overlayTouchListener?.onTouchExplorationStateChanged(true)
+                    useExpandedOverlay = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
                 }
             } catch (e: RuntimeException) {
                 Log.e(TAG, "showUdfpsOverlay | failed to add window", e)
@@ -225,13 +234,14 @@
             REASON_ENROLL_ENROLLING -> {
                 UdfpsEnrollViewController(
                     view.addUdfpsView(R.layout.udfps_enroll_view) {
-                        updateSensorLocation(overlayParams.sensorBounds)
+                        updateSensorLocation(sensorBounds)
                     },
                     enrollHelper ?: throw IllegalStateException("no enrollment helper"),
                     statusBarStateController,
                     shadeExpansionStateManager,
                     dialogManager,
                     dumpManager,
+                    featureFlags,
                     overlayParams.scaleFactor
                 )
             }
@@ -420,7 +430,12 @@
         }
 
         // Original sensorBounds assume portrait mode.
-        val rotatedSensorBounds = Rect(overlayParams.sensorBounds)
+        var rotatedBounds =
+            if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+                Rect(overlayParams.overlayBounds)
+            } else {
+                Rect(overlayParams.sensorBounds)
+            }
 
         val rot = overlayParams.rotation
         if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
@@ -434,18 +449,27 @@
             } else {
                 Log.v(TAG, "Rotate UDFPS bounds " + Surface.rotationToString(rot))
                 RotationUtils.rotateBounds(
-                    rotatedSensorBounds,
+                    rotatedBounds,
                     overlayParams.naturalDisplayWidth,
                     overlayParams.naturalDisplayHeight,
                     rot
                 )
+
+                if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+                    RotationUtils.rotateBounds(
+                            sensorBounds,
+                            overlayParams.naturalDisplayWidth,
+                            overlayParams.naturalDisplayHeight,
+                            rot
+                    )
+                }
             }
         }
 
-        x = rotatedSensorBounds.left - paddingX
-        y = rotatedSensorBounds.top - paddingY
-        height = rotatedSensorBounds.height() + 2 * paddingX
-        width = rotatedSensorBounds.width() + 2 * paddingY
+        x = rotatedBounds.left - paddingX
+        y = rotatedBounds.top - paddingY
+        height = rotatedBounds.height() + 2 * paddingX
+        width = rotatedBounds.width() + 2 * paddingY
 
         return this
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEllipseDetection.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEllipseDetection.kt
new file mode 100644
index 0000000..8ae4775
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEllipseDetection.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import android.graphics.Point
+import android.graphics.Rect
+import android.util.RotationUtils
+import android.view.MotionEvent
+import kotlin.math.cos
+import kotlin.math.pow
+import kotlin.math.sin
+
+private const val TAG = "UdfpsEllipseDetection"
+
+private const val NEEDED_POINTS = 2
+
+class UdfpsEllipseDetection(overlayParams: UdfpsOverlayParams) {
+    var sensorRect = Rect()
+    var points: Array<Point> = emptyArray()
+
+    init {
+        sensorRect = Rect(overlayParams.sensorBounds)
+
+        points = calculateSensorPoints(sensorRect)
+    }
+
+    fun updateOverlayParams(params: UdfpsOverlayParams) {
+        sensorRect = Rect(params.sensorBounds)
+
+        val rot = params.rotation
+        RotationUtils.rotateBounds(
+            sensorRect,
+            params.naturalDisplayWidth,
+            params.naturalDisplayHeight,
+            rot
+        )
+
+        points = calculateSensorPoints(sensorRect)
+    }
+
+    fun isGoodEllipseOverlap(event: MotionEvent): Boolean {
+        return points.count { checkPoint(event, it) } >= NEEDED_POINTS
+    }
+
+    private fun checkPoint(event: MotionEvent, point: Point): Boolean {
+        // Calculate if sensor point is within ellipse
+        // Formula: ((cos(o)(xE - xS) + sin(o)(yE - yS))^2 / a^2) + ((sin(o)(xE - xS) + cos(o)(yE -
+        // yS))^2 / b^2) <= 1
+        val a: Float = cos(event.orientation) * (point.x - event.rawX)
+        val b: Float = sin(event.orientation) * (point.y - event.rawY)
+        val c: Float = sin(event.orientation) * (point.x - event.rawX)
+        val d: Float = cos(event.orientation) * (point.y - event.rawY)
+        val result =
+            (a + b).pow(2) / (event.touchMinor / 2).pow(2) +
+                (c - d).pow(2) / (event.touchMajor / 2).pow(2)
+
+        return result <= 1
+    }
+}
+
+fun calculateSensorPoints(sensorRect: Rect): Array<Point> {
+    val sensorX = sensorRect.centerX()
+    val sensorY = sensorRect.centerY()
+    val cornerOffset: Int = sensorRect.width() / 4
+    val sideOffset: Int = sensorRect.width() / 3
+
+    return arrayOf(
+        Point(sensorX - cornerOffset, sensorY - cornerOffset),
+        Point(sensorX, sensorY - sideOffset),
+        Point(sensorX + cornerOffset, sensorY - cornerOffset),
+        Point(sensorX - sideOffset, sensorY),
+        Point(sensorX, sensorY),
+        Point(sensorX + sideOffset, sensorY),
+        Point(sensorX - cornerOffset, sensorY + cornerOffset),
+        Point(sensorX, sensorY + sideOffset),
+        Point(sensorX + cornerOffset, sensorY + cornerOffset)
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
index e5c4855..1cc4141 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.AttributeSet;
@@ -41,6 +42,9 @@
     @NonNull private ImageView mFingerprintView;
     @NonNull private ImageView mFingerprintProgressView;
 
+    private LayoutParams mProgressParams;
+    private float mProgressBarRadius;
+
     public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
@@ -57,6 +61,32 @@
     }
 
     @Override
+    void onSensorRectUpdated(RectF bounds) {
+        if (mUseExpandedOverlay) {
+            RectF converted = getBoundsRelativeToView(bounds);
+
+            mProgressParams = new LayoutParams(
+                    (int) (converted.width() + mProgressBarRadius * 2),
+                    (int) (converted.height() + mProgressBarRadius * 2));
+            mProgressParams.setMargins(
+                    (int) (converted.left - mProgressBarRadius),
+                    (int) (converted.top - mProgressBarRadius),
+                    (int) (converted.right + mProgressBarRadius),
+                    (int) (converted.bottom + mProgressBarRadius)
+            );
+
+            mFingerprintProgressView.setLayoutParams(mProgressParams);
+            super.onSensorRectUpdated(converted);
+        } else {
+            super.onSensorRectUpdated(bounds);
+        }
+    }
+
+    void setProgressBarRadius(float radius) {
+        mProgressBarRadius = radius;
+    }
+
+    @Override
     public UdfpsDrawable getDrawable() {
         return mFingerprintDrawable;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index e01273f..4017665 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -21,6 +21,8 @@
 
 import com.android.systemui.R;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeExpansionStateManager;
 import com.android.systemui.statusbar.phone.SystemUIDialogManager;
@@ -57,6 +59,7 @@
             @NonNull ShadeExpansionStateManager shadeExpansionStateManager,
             @NonNull SystemUIDialogManager systemUIDialogManager,
             @NonNull DumpManager dumpManager,
+            @NonNull FeatureFlags featureFlags,
             float scaleFactor) {
         super(view, statusBarStateController, shadeExpansionStateManager, systemUIDialogManager,
                 dumpManager);
@@ -64,6 +67,11 @@
                 R.integer.config_udfpsEnrollProgressBar));
         mEnrollHelper = enrollHelper;
         mView.setEnrollHelper(mEnrollHelper);
+        mView.setProgressBarRadius(mEnrollProgressBarRadius);
+
+        if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
+            mView.mUseExpandedOverlay = true;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index bc274a0..339b8ca 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.util.MathUtils;
 import android.view.View;
@@ -75,6 +76,8 @@
     private int mAnimationType = ANIMATION_NONE;
     private boolean mFullyInflated;
 
+    private LayoutParams mParams;
+
     public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -239,6 +242,22 @@
         updateAlpha();
     }
 
+    @Override
+    void onSensorRectUpdated(RectF bounds) {
+        super.onSensorRectUpdated(bounds);
+
+        if (mUseExpandedOverlay) {
+            mParams = new LayoutParams((int) bounds.width(), (int) bounds.height());
+            RectF converted = getBoundsRelativeToView(bounds);
+            mParams.setMargins(
+                    (int) converted.left,
+                    (int) converted.top,
+                    (int) converted.right,
+                    (int) converted.bottom
+            );
+        }
+    }
+
     /**
      * Animates in the bg protection circle behind the fp icon to highlight the icon.
      */
@@ -277,6 +296,7 @@
         pw.println("    mUdfpsRequested=" + mUdfpsRequested);
         pw.println("    mInterpolatedDarkAmount=" + mInterpolatedDarkAmount);
         pw.println("    mAnimationType=" + mAnimationType);
+        pw.println("    mUseExpandedOverlay=" + mUseExpandedOverlay);
     }
 
     private final AsyncLayoutInflater.OnInflateFinishedListener mLayoutInflaterFinishListener =
@@ -291,7 +311,12 @@
             updatePadding();
             updateColor();
             updateAlpha();
-            parent.addView(view);
+
+            if (mUseExpandedOverlay) {
+                parent.addView(view, mParams);
+            } else {
+                parent.addView(view);
+            }
 
             // requires call to invalidate to update the color
             mLockScreenFp.addValueCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 91967f9..63144fc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -52,7 +52,6 @@
 import java.io.PrintWriter
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 
 /** Class that coordinates non-HBM animations during keyguard authentication. */
@@ -82,6 +81,8 @@
         systemUIDialogManager,
         dumpManager
     ) {
+    private val useExpandedOverlay: Boolean =
+        featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
     private val isModernBouncerEnabled: Boolean = featureFlags.isEnabled(Flags.MODERN_BOUNCER)
     private var showingUdfpsBouncer = false
     private var udfpsRequested = false
@@ -233,7 +234,13 @@
                 if (transitionToFullShadeProgress != 0f) {
                     return
                 }
-                udfpsController.onTouch(event)
+
+                // Forwarding touches not needed with expanded overlay
+                if (useExpandedOverlay) {
+                    return
+                } else {
+                    udfpsController.onTouch(event)
+                }
             }
         }
 
@@ -322,6 +329,7 @@
         keyguardViewManager.setAlternateBouncer(mAlternateBouncer)
         lockScreenShadeTransitionController.udfpsKeyguardViewController = this
         activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
+        view.mUseExpandedOverlay = useExpandedOverlay
     }
 
     override fun onViewDetached() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
index a15456d..4a8877e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
@@ -20,6 +20,7 @@
 import android.graphics.Color
 import android.graphics.Paint
 import android.graphics.PointF
+import android.graphics.Rect
 import android.graphics.RectF
 import android.util.AttributeSet
 import android.util.Log
@@ -38,9 +39,12 @@
     attrs: AttributeSet?
 ) : FrameLayout(context, attrs), DozeReceiver {
 
+    // Use expanded overlay when feature flag is true, set by UdfpsViewController
+    var useExpandedOverlay: Boolean = false
+
     // sensorRect may be bigger than the sensor. True sensor dimensions are defined in
     // overlayParams.sensorBounds
-    private val sensorRect = RectF()
+    var sensorRect = Rect()
     private var mUdfpsDisplayMode: UdfpsDisplayModeProvider? = null
     private val debugTextPaint = Paint().apply {
         isAntiAlias = true
@@ -92,13 +96,19 @@
         val paddingX = animationViewController?.paddingX ?: 0
         val paddingY = animationViewController?.paddingY ?: 0
 
-        sensorRect.set(
-            paddingX.toFloat(),
-            paddingY.toFloat(),
-            (overlayParams.sensorBounds.width() + paddingX).toFloat(),
-            (overlayParams.sensorBounds.height() + paddingY).toFloat()
-        )
-        animationViewController?.onSensorRectUpdated(RectF(sensorRect))
+        // Updates sensor rect in relation to the overlay view
+        if (useExpandedOverlay) {
+            animationViewController?.onSensorRectUpdated(RectF(sensorRect))
+        } else {
+            sensorRect.set(
+                    paddingX,
+                    paddingY,
+                    (overlayParams.sensorBounds.width() + paddingX),
+                    (overlayParams.sensorBounds.height() + paddingY)
+            )
+
+            animationViewController?.onSensorRectUpdated(RectF(sensorRect))
+        }
     }
 
     fun onTouchOutsideView() {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
index 616e49c..1454210 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.ripple.RippleView
+import com.android.systemui.surfaceeffects.ripple.RippleView
 import com.android.systemui.statusbar.commandline.Command
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.policy.BatteryController
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
index e82d0ea..3808ab7 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
@@ -30,7 +30,7 @@
 
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.ripple.RippleShader.RippleShape;
+import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
 
 /**
  * A WirelessChargingAnimation is a view containing view + animation for wireless charging.
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 1455699..36103f8 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -33,9 +33,9 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
-import com.android.systemui.ripple.RippleAnimationConfig;
-import com.android.systemui.ripple.RippleShader.RippleShape;
-import com.android.systemui.ripple.RippleView;
+import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
+import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
+import com.android.systemui.surfaceeffects.ripple.RippleView;
 
 import java.text.NumberFormat;
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index beaccba..e8e1f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -231,7 +231,8 @@
 
         // check for false tap if it is a seekbar interaction
         if (interactionType == MEDIA_SEEKBAR) {
-            localResult[0] &= isFalseTap(LOW_PENALTY);
+            localResult[0] &= isFalseTap(mFeatureFlags.isEnabled(Flags.MEDIA_FALSING_PENALTY)
+                    ? FalsingManager.MODERATE_PENALTY : FalsingManager.LOW_PENALTY);
         }
 
         logDebug("False Gesture (type: " + interactionType + "): " + localResult[0]);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
index 588ef5c..4dfcd63 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
@@ -16,16 +16,120 @@
 
 package com.android.systemui.controls
 
+import android.Manifest
+import android.content.ComponentName
 import android.content.Context
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE
+import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+import android.content.pm.ResolveInfo
 import android.content.pm.ServiceInfo
+import android.os.UserHandle
+import android.service.controls.ControlsProviderService
+import androidx.annotation.WorkerThread
 import com.android.settingslib.applications.DefaultAppInfo
+import java.util.Objects
 
 class ControlsServiceInfo(
-    context: Context,
+    private val context: Context,
     val serviceInfo: ServiceInfo
 ) : DefaultAppInfo(
     context,
     context.packageManager,
     context.userId,
     serviceInfo.componentName
-)
\ No newline at end of file
+) {
+    private val _panelActivity: ComponentName?
+
+    init {
+        val metadata = serviceInfo.metaData
+                ?.getString(ControlsProviderService.META_DATA_PANEL_ACTIVITY) ?: ""
+        val unflatenned = ComponentName.unflattenFromString(metadata)
+        if (unflatenned != null && unflatenned.packageName == componentName.packageName) {
+            _panelActivity = unflatenned
+        } else {
+            _panelActivity = null
+        }
+    }
+
+    /**
+     * Component name of an activity that will be shown embedded in the device controls space
+     * instead of using the controls rendered by SystemUI.
+     *
+     * The activity must be in the same package, exported, enabled and protected by the
+     * [Manifest.permission.BIND_CONTROLS] permission.
+     */
+    var panelActivity: ComponentName? = null
+        private set
+
+    private var resolved: Boolean = false
+
+    @WorkerThread
+    fun resolvePanelActivity() {
+        if (resolved) return
+        resolved = true
+        panelActivity = _panelActivity?.let {
+            val resolveInfos = mPm.queryIntentActivitiesAsUser(
+                    Intent().setComponent(it),
+                    PackageManager.ResolveInfoFlags.of(
+                            MATCH_DIRECT_BOOT_AWARE.toLong() or
+                                    MATCH_DIRECT_BOOT_UNAWARE.toLong()
+                    ),
+                    UserHandle.of(userId)
+            )
+            if (resolveInfos.isNotEmpty() && verifyResolveInfo(resolveInfos[0])) {
+                it
+            } else {
+                null
+            }
+        }
+    }
+
+    /**
+     * Verifies that the panel activity is enabled, exported and protected by the correct
+     * permission. This last check is to prevent apps from forgetting to protect the activity, as
+     * they won't be able to see the panel until they do.
+     */
+    @WorkerThread
+    private fun verifyResolveInfo(resolveInfo: ResolveInfo): Boolean {
+        return resolveInfo.activityInfo?.let {
+            it.permission == Manifest.permission.BIND_CONTROLS &&
+                    it.exported && isComponentActuallyEnabled(it)
+        } ?: false
+    }
+
+    @WorkerThread
+    private fun isComponentActuallyEnabled(activityInfo: ActivityInfo): Boolean {
+        return when (mPm.getComponentEnabledSetting(activityInfo.componentName)) {
+            PackageManager.COMPONENT_ENABLED_STATE_ENABLED -> true
+            PackageManager.COMPONENT_ENABLED_STATE_DISABLED -> false
+            PackageManager.COMPONENT_ENABLED_STATE_DEFAULT -> activityInfo.enabled
+            else -> false
+        }
+    }
+
+    override fun equals(other: Any?): Boolean {
+        return other is ControlsServiceInfo &&
+                userId == other.userId &&
+                componentName == other.componentName &&
+                panelActivity == other.panelActivity
+    }
+
+    override fun hashCode(): Int {
+        return Objects.hash(userId, componentName, panelActivity)
+    }
+
+    fun copy(): ControlsServiceInfo {
+        return ControlsServiceInfo(context, serviceInfo).also {
+            it.panelActivity = this.panelActivity
+        }
+    }
+
+    override fun toString(): String {
+        return """
+            ControlsServiceInfo(serviceInfo=$serviceInfo, panelActivity=$panelActivity, resolved=$resolved)
+        """.trimIndent()
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index b11103a..7df0865 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -18,6 +18,7 @@
 
 import android.app.ActivityOptions
 import android.content.ComponentName
+import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import android.util.Log
@@ -33,21 +34,23 @@
 import androidx.recyclerview.widget.ItemTouchHelper
 import androidx.recyclerview.widget.RecyclerView
 import com.android.systemui.R
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.CustomIconCache
 import com.android.systemui.controls.controller.ControlsControllerImpl
 import com.android.systemui.controls.controller.StructureInfo
 import com.android.systemui.controls.ui.ControlsActivity
 import com.android.systemui.controls.ui.ControlsUiController
-import com.android.systemui.settings.CurrentUserTracker
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.settings.UserTracker
+import java.util.concurrent.Executor
 import javax.inject.Inject
 
 /**
  * Activity for rearranging and removing controls for a given structure
  */
 open class ControlsEditingActivity @Inject constructor(
+    @Main private val mainExecutor: Executor,
     private val controller: ControlsControllerImpl,
-    private val broadcastDispatcher: BroadcastDispatcher,
+    private val userTracker: UserTracker,
     private val customIconCache: CustomIconCache,
     private val uiController: ControlsUiController
 ) : ComponentActivity() {
@@ -66,12 +69,12 @@
     private lateinit var subtitle: TextView
     private lateinit var saveButton: View
 
-    private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
+    private val userTrackerCallback: UserTracker.Callback = object : UserTracker.Callback {
         private val startingUser = controller.currentUserId
 
-        override fun onUserSwitched(newUserId: Int) {
-            if (newUserId != startingUser) {
-                stopTracking()
+        override fun onUserChanged(newUser: Int, userContext: Context) {
+            if (newUser != startingUser) {
+                userTracker.removeCallback(this)
                 finish()
             }
         }
@@ -104,7 +107,7 @@
         super.onStart()
         setUpList()
 
-        currentUserTracker.startTracking()
+        userTracker.addCallback(userTrackerCallback, mainExecutor)
 
         if (DEBUG) {
             Log.d(TAG, "Registered onBackInvokedCallback")
@@ -115,7 +118,7 @@
 
     override fun onStop() {
         super.onStop()
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
 
         if (DEBUG) {
             Log.d(TAG, "Unregistered onBackInvokedCallback")
@@ -248,7 +251,7 @@
     }
 
     override fun onDestroy() {
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
         super.onDestroy()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 9b2a728..3e97d31 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter
 import android.app.ActivityOptions
 import android.content.ComponentName
+import android.content.Context
 import android.content.Intent
 import android.content.res.Configuration
 import android.os.Bundle
@@ -39,7 +40,6 @@
 import androidx.viewpager2.widget.ViewPager2
 import com.android.systemui.Prefs
 import com.android.systemui.R
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.TooltipManager
 import com.android.systemui.controls.controller.ControlsControllerImpl
@@ -47,7 +47,7 @@
 import com.android.systemui.controls.ui.ControlsActivity
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.settings.CurrentUserTracker
+import com.android.systemui.settings.UserTracker
 import java.text.Collator
 import java.util.concurrent.Executor
 import java.util.function.Consumer
@@ -57,7 +57,7 @@
     @Main private val executor: Executor,
     private val controller: ControlsControllerImpl,
     private val listingController: ControlsListingController,
-    private val broadcastDispatcher: BroadcastDispatcher,
+    private val userTracker: UserTracker,
     private val uiController: ControlsUiController
 ) : ComponentActivity() {
 
@@ -95,12 +95,12 @@
     private var cancelLoadRunnable: Runnable? = null
     private var isPagerLoaded = false
 
-    private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
+    private val userTrackerCallback: UserTracker.Callback = object : UserTracker.Callback {
         private val startingUser = controller.currentUserId
 
-        override fun onUserSwitched(newUserId: Int) {
-            if (newUserId != startingUser) {
-                stopTracking()
+        override fun onUserChanged(newUser: Int, userContext: Context) {
+            if (newUser != startingUser) {
+                userTracker.removeCallback(this)
                 finish()
             }
         }
@@ -363,7 +363,7 @@
         super.onStart()
 
         listingController.addCallback(listingCallback)
-        currentUserTracker.startTracking()
+        userTracker.addCallback(userTrackerCallback, executor)
 
         if (DEBUG) {
             Log.d(TAG, "Registered onBackInvokedCallback")
@@ -388,7 +388,7 @@
         super.onStop()
 
         listingController.removeCallback(listingCallback)
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
 
         if (DEBUG) {
             Log.d(TAG, "Unregistered onBackInvokedCallback")
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
index 2d76ff2..c6428ef 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
@@ -18,17 +18,23 @@
 
 import android.content.ComponentName
 import android.content.Context
-import android.content.pm.ServiceInfo
 import android.os.UserHandle
 import android.service.controls.ControlsProviderService
 import android.util.Log
 import com.android.internal.annotations.VisibleForTesting
 import com.android.settingslib.applications.ServiceListing
 import com.android.settingslib.widget.CandidateInfo
+import com.android.systemui.Dumpable
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.indentIfPossible
+import java.io.PrintWriter
 import java.util.concurrent.Executor
 import java.util.concurrent.atomic.AtomicInteger
 import javax.inject.Inject
@@ -57,16 +63,19 @@
     private val context: Context,
     @Background private val backgroundExecutor: Executor,
     private val serviceListingBuilder: (Context) -> ServiceListing,
-    userTracker: UserTracker
-) : ControlsListingController {
+    private val userTracker: UserTracker,
+    dumpManager: DumpManager,
+    featureFlags: FeatureFlags
+) : ControlsListingController, Dumpable {
 
     @Inject
-    constructor(context: Context, executor: Executor, userTracker: UserTracker): this(
-            context,
-            executor,
-            ::createServiceListing,
-            userTracker
-    )
+    constructor(
+            context: Context,
+            @Background executor: Executor,
+            userTracker: UserTracker,
+            dumpManager: DumpManager,
+            featureFlags: FeatureFlags
+    ) : this(context, executor, ::createServiceListing, userTracker, dumpManager, featureFlags)
 
     private var serviceListing = serviceListingBuilder(context)
     // All operations in background thread
@@ -76,27 +85,26 @@
         private const val TAG = "ControlsListingControllerImpl"
     }
 
-    private var availableComponents = emptySet<ComponentName>()
-    private var availableServices = emptyList<ServiceInfo>()
+    private var availableServices = emptyList<ControlsServiceInfo>()
     private var userChangeInProgress = AtomicInteger(0)
 
     override var currentUserId = userTracker.userId
         private set
 
-    private val serviceListingCallback = ServiceListing.Callback {
-        val newServices = it.toList()
-        val newComponents =
-            newServices.mapTo(mutableSetOf<ComponentName>(), { s -> s.getComponentName() })
-
+    private val serviceListingCallback = ServiceListing.Callback { list ->
+        Log.d(TAG, "ServiceConfig reloaded, count: ${list.size}")
+        val newServices = list.map { ControlsServiceInfo(userTracker.userContext, it) }
+        // After here, `list` is not captured, so we don't risk modifying it outside of the callback
         backgroundExecutor.execute {
             if (userChangeInProgress.get() > 0) return@execute
-            if (!newComponents.equals(availableComponents)) {
-                Log.d(TAG, "ServiceConfig reloaded, count: ${newComponents.size}")
-                availableComponents = newComponents
+            if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
+                newServices.forEach(ControlsServiceInfo::resolvePanelActivity)
+            }
+
+            if (newServices != availableServices) {
                 availableServices = newServices
-                val currentServices = getCurrentServices()
                 callbacks.forEach {
-                    it.onServicesUpdated(currentServices)
+                    it.onServicesUpdated(getCurrentServices())
                 }
             }
         }
@@ -104,6 +112,7 @@
 
     init {
         Log.d(TAG, "Initializing")
+        dumpManager.registerDumpable(TAG, this)
         serviceListing.addCallback(serviceListingCallback)
         serviceListing.setListening(true)
         serviceListing.reload()
@@ -165,7 +174,7 @@
      *         [ControlsProviderService]
      */
     override fun getCurrentServices(): List<ControlsServiceInfo> =
-            availableServices.map { ControlsServiceInfo(context, it) }
+            availableServices.map(ControlsServiceInfo::copy)
 
     /**
      * Get the localized label for the component.
@@ -174,7 +183,15 @@
      * @return a label as returned by [CandidateInfo.loadLabel] or `null`.
      */
     override fun getAppLabel(name: ComponentName): CharSequence? {
-        return getCurrentServices().firstOrNull { it.componentName == name }
+        return availableServices.firstOrNull { it.componentName == name }
                 ?.loadLabel()
     }
+
+    override fun dump(writer: PrintWriter, args: Array<out String>) {
+        writer.println("ControlsListingController:")
+        writer.asIndenting().indentIfPossible {
+            println("Callbacks: $callbacks")
+            println("Services: ${getCurrentServices()}")
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 47690a7..90bc5d0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -18,6 +18,7 @@
 
 import android.app.ActivityOptions
 import android.content.ComponentName
+import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import android.util.Log
@@ -33,13 +34,12 @@
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.systemui.R
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.ui.ControlsActivity
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.settings.CurrentUserTracker
+import com.android.systemui.settings.UserTracker
 import java.util.concurrent.Executor
 import javax.inject.Inject
 
@@ -51,7 +51,7 @@
     @Background private val backExecutor: Executor,
     private val listingController: ControlsListingController,
     private val controlsController: ControlsController,
-    private val broadcastDispatcher: BroadcastDispatcher,
+    private val userTracker: UserTracker,
     private val uiController: ControlsUiController
 ) : ComponentActivity() {
 
@@ -62,12 +62,12 @@
     }
     private var backShouldExit = false
     private lateinit var recyclerView: RecyclerView
-    private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
+    private val userTrackerCallback: UserTracker.Callback = object : UserTracker.Callback {
         private val startingUser = listingController.currentUserId
 
-        override fun onUserSwitched(newUserId: Int) {
-            if (newUserId != startingUser) {
-                stopTracking()
+        override fun onUserChanged(newUser: Int, userContext: Context) {
+            if (newUser != startingUser) {
+                userTracker.removeCallback(this)
                 finish()
             }
         }
@@ -129,7 +129,7 @@
 
     override fun onStart() {
         super.onStart()
-        currentUserTracker.startTracking()
+        userTracker.addCallback(userTrackerCallback, executor)
 
         recyclerView.alpha = 0.0f
         recyclerView.adapter = AppAdapter(
@@ -161,7 +161,7 @@
 
     override fun onStop() {
         super.onStop()
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
 
         if (DEBUG) {
             Log.d(TAG, "Unregistered onBackInvokedCallback")
@@ -190,7 +190,7 @@
     }
 
     override fun onDestroy() {
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
         super.onDestroy()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
index b376455..86bde5c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
@@ -19,6 +19,7 @@
 import android.app.AlertDialog
 import android.app.Dialog
 import android.content.ComponentName
+import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
 import android.os.Bundle
@@ -32,18 +33,20 @@
 import android.widget.TextView
 import androidx.activity.ComponentActivity
 import com.android.systemui.R
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.controller.ControlInfo
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.ui.RenderInfo
-import com.android.systemui.settings.CurrentUserTracker
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.concurrent.Executor
 import javax.inject.Inject
 
 open class ControlsRequestDialog @Inject constructor(
+    @Main private val mainExecutor: Executor,
     private val controller: ControlsController,
-    private val broadcastDispatcher: BroadcastDispatcher,
+    private val userTracker: UserTracker,
     private val controlsListingController: ControlsListingController
 ) : ComponentActivity(), DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
 
@@ -58,12 +61,12 @@
         override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {}
     }
 
-    private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
+    private val userTrackerCallback: UserTracker.Callback = object : UserTracker.Callback {
         private val startingUser = controller.currentUserId
 
-        override fun onUserSwitched(newUserId: Int) {
-            if (newUserId != startingUser) {
-                stopTracking()
+        override fun onUserChanged(newUser: Int, userContext: Context) {
+            if (newUser != startingUser) {
+                userTracker.removeCallback(this)
                 finish()
             }
         }
@@ -72,7 +75,7 @@
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
-        currentUserTracker.startTracking()
+        userTracker.addCallback(userTrackerCallback, mainExecutor)
         controlsListingController.addCallback(callback)
 
         val requestUser = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL)
@@ -118,7 +121,7 @@
 
     override fun onDestroy() {
         dialog?.dismiss()
-        currentUserTracker.stopTracking()
+        userTracker.removeCallback(userTrackerCallback)
         controlsListingController.removeCallback(callback)
         super.onDestroy()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 139a8b7..b8030b2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -17,6 +17,7 @@
 package com.android.systemui.dagger;
 
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
@@ -68,6 +69,7 @@
 import android.os.ServiceManager;
 import android.os.UserManager;
 import android.os.Vibrator;
+import android.os.storage.StorageManager;
 import android.permission.PermissionManager;
 import android.safetycenter.SafetyCenterManager;
 import android.service.dreams.DreamService;
@@ -109,6 +111,7 @@
 /**
  * Provides Non-SystemUI, Framework-Owned instances to the dependency graph.
  */
+@SuppressLint("NonInjectedService")
 @Module
 public class FrameworkServicesModule {
     @Provides
@@ -462,7 +465,13 @@
 
     @Provides
     @Singleton
-    static SubscriptionManager provideSubcriptionManager(Context context) {
+    static StorageManager provideStorageManager(Context context) {
+        return context.getSystemService(StorageManager.class);
+    }
+
+    @Provides
+    @Singleton
+    static SubscriptionManager provideSubscriptionManager(Context context) {
         return context.getSystemService(SubscriptionManager.class);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index fe89c9a..9e8c0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -21,24 +21,21 @@
 import com.android.systemui.dagger.qualifiers.InstrumentationTest;
 import com.android.systemui.util.InitializationChecker;
 
-import javax.inject.Singleton;
-
 import dagger.BindsInstance;
-import dagger.Component;
 
 /**
  * Base root component for Dagger injection.
  *
+ * This class is not actually annotated as a Dagger component, since it is not used directly as one.
+ * Doing so generates unnecessary code bloat.
+ *
  * See {@link ReferenceGlobalRootComponent} for the one actually used by AOSP.
  */
-@Singleton
-@Component(modules = {GlobalModule.class})
 public interface GlobalRootComponent {
 
     /**
      * Builder for a GlobalRootComponent.
      */
-    @Component.Builder
     interface Builder {
         @BindsInstance
         Builder context(Context context);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
index 7ab36e8..b30e0c2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.dagger;
 
+import com.android.systemui.keyguard.KeyguardQuickAffordanceProvider;
+import com.android.systemui.statusbar.NotificationInsetsModule;
 import com.android.systemui.statusbar.QsFrameTranslateModule;
 
 import dagger.Subcomponent;
@@ -27,6 +29,7 @@
 @Subcomponent(modules = {
         DefaultComponentBinder.class,
         DependencyProvider.class,
+        NotificationInsetsModule.class,
         QsFrameTranslateModule.class,
         SystemUIBinder.class,
         SystemUIModule.class,
@@ -42,4 +45,9 @@
     interface Builder extends SysUIComponent.Builder {
         ReferenceSysUIComponent build();
     }
+
+    /**
+     * Member injection into the supplied argument.
+     */
+    void inject(KeyguardQuickAffordanceProvider keyguardQuickAffordanceProvider);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index a14b0ee..6dc4f5c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -28,6 +28,7 @@
 import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionCli;
 import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
 import com.android.systemui.people.PeopleProvider;
+import com.android.systemui.statusbar.NotificationInsetsModule;
 import com.android.systemui.statusbar.QsFrameTranslateModule;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.unfold.FoldStateLogger;
@@ -65,6 +66,7 @@
 @Subcomponent(modules = {
         DefaultComponentBinder.class,
         DependencyProvider.class,
+        NotificationInsetsModule.class,
         QsFrameTranslateModule.class,
         SystemUIBinder.class,
         SystemUIModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index d537d4b..000bbe6 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -54,6 +54,9 @@
     private val receiverMap: Map<String, MutableList<DemoMode>>
 
     init {
+        // Don't persist demo mode across restarts.
+        requestFinishDemoMode()
+
         val m = mutableMapOf<String, MutableList<DemoMode>>()
         DemoMode.COMMANDS.map { command ->
             m.put(command, mutableListOf())
@@ -74,7 +77,6 @@
         // content changes to know if the setting turned on or off
         tracker.startTracking()
 
-        // TODO: We should probably exit demo mode if we booted up with it on
         isInDemoMode = tracker.isInDemoMode
 
         val demoFilter = IntentFilter()
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index b69afeb..0c14ed5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -133,9 +133,9 @@
     /**
      * Appends fling event to the logs
      */
-    public void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded,
+    public void traceFling(boolean expand, boolean aboveThreshold,
             boolean screenOnFromTouch) {
-        mLogger.logFling(expand, aboveThreshold, thresholdNeeded, screenOnFromTouch);
+        mLogger.logFling(expand, aboveThreshold, screenOnFromTouch);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index 18c8e01..b5dbe21 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -96,13 +96,11 @@
     fun logFling(
         expand: Boolean,
         aboveThreshold: Boolean,
-        thresholdNeeded: Boolean,
         screenOnFromTouch: Boolean
     ) {
         buffer.log(TAG, DEBUG, {
             bool1 = expand
             bool2 = aboveThreshold
-            bool3 = thresholdNeeded
             bool4 = screenOnFromTouch
         }, {
             "Fling expand=$bool1 aboveThreshold=$bool2 thresholdNeeded=$bool3 " +
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 9a091e7..833ff3f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -22,7 +22,6 @@
 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
 
 import android.annotation.AnyThread;
-import android.app.ActivityManager;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
@@ -47,6 +46,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.plugins.SensorManagerPlugin;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -96,6 +96,7 @@
     private final SecureSettings mSecureSettings;
     private final DevicePostureController mDevicePostureController;
     private final AuthController mAuthController;
+    private final UserTracker mUserTracker;
     private final boolean mScreenOffUdfpsEnabled;
 
     // Sensors
@@ -149,7 +150,8 @@
             ProximitySensor proximitySensor,
             SecureSettings secureSettings,
             AuthController authController,
-            DevicePostureController devicePostureController
+            DevicePostureController devicePostureController,
+            UserTracker userTracker
     ) {
         mSensorManager = sensorManager;
         mConfig = config;
@@ -167,6 +169,7 @@
         mDevicePostureController = devicePostureController;
         mDevicePosture = mDevicePostureController.getDevicePosture();
         mAuthController = authController;
+        mUserTracker = userTracker;
 
         mUdfpsEnrolled =
                 mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
@@ -438,7 +441,7 @@
     private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange, Collection<Uri> uris, int flags, int userId) {
-            if (userId != ActivityManager.getCurrentUser()) {
+            if (userId != mUserTracker.getUserId()) {
                 return;
             }
             for (TriggerSensor s : mTriggerSensors) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 32cb1c0..0b69b80 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -45,6 +45,7 @@
 import com.android.systemui.doze.DozeMachine.State;
 import com.android.systemui.doze.dagger.DozeScope;
 import com.android.systemui.log.SessionTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -188,7 +189,8 @@
             UiEventLogger uiEventLogger,
             SessionTracker sessionTracker,
             KeyguardStateController keyguardStateController,
-            DevicePostureController devicePostureController) {
+            DevicePostureController devicePostureController,
+            UserTracker userTracker) {
         mContext = context;
         mDozeHost = dozeHost;
         mConfig = config;
@@ -200,7 +202,7 @@
 
         mDozeSensors = new DozeSensors(mSensorManager, dozeParameters,
                 config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor,
-                secureSettings, authController, devicePostureController);
+                secureSettings, authController, devicePostureController, userTracker);
         mDockManager = dockManager;
         mProxCheck = proxCheck;
         mDozeLog = dozeLog;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index d8dd6a2..0087c84 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -17,17 +17,19 @@
 package com.android.systemui.dreams
 
 import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
 import android.animation.AnimatorSet
 import android.animation.ValueAnimator
 import android.view.View
+import android.view.animation.Interpolator
+import androidx.annotation.FloatRange
 import androidx.core.animation.doOnEnd
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dreams.complication.ComplicationHostViewController
 import com.android.systemui.dreams.complication.ComplicationLayoutParams
+import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position
 import com.android.systemui.dreams.dagger.DreamOverlayModule
 import com.android.systemui.statusbar.BlurUtils
-import java.util.function.Consumer
+import com.android.systemui.statusbar.CrossFadeHelper
 import javax.inject.Inject
 import javax.inject.Named
 
@@ -40,108 +42,239 @@
     private val mStatusBarViewController: DreamOverlayStatusBarViewController,
     private val mOverlayStateController: DreamOverlayStateController,
     @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
-    private val mDreamInBlurAnimDuration: Int,
-    @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY) private val mDreamInBlurAnimDelay: Int,
+    private val mDreamInBlurAnimDurationMs: Long,
+    @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY)
+    private val mDreamInBlurAnimDelayMs: Long,
     @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
-    private val mDreamInComplicationsAnimDuration: Int,
+    private val mDreamInComplicationsAnimDurationMs: Long,
     @Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
-    private val mDreamInTopComplicationsAnimDelay: Int,
+    private val mDreamInTopComplicationsAnimDelayMs: Long,
     @Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
-    private val mDreamInBottomComplicationsAnimDelay: Int
+    private val mDreamInBottomComplicationsAnimDelayMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DISTANCE)
+    private val mDreamOutTranslationYDistance: Int,
+    @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DURATION)
+    private val mDreamOutTranslationYDurationMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
+    private val mDreamOutTranslationYDelayBottomMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
+    private val mDreamOutTranslationYDelayTopMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DURATION) private val mDreamOutAlphaDurationMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_BOTTOM)
+    private val mDreamOutAlphaDelayBottomMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_TOP) private val mDreamOutAlphaDelayTopMs: Long,
+    @Named(DreamOverlayModule.DREAM_OUT_BLUR_DURATION) private val mDreamOutBlurDurationMs: Long
 ) {
 
-    var mEntryAnimations: AnimatorSet? = null
+    private var mAnimator: Animator? = null
+
+    /**
+     * Store the current alphas at the various positions. This is so that we may resume an animation
+     * at the current alpha.
+     */
+    private var mCurrentAlphaAtPosition = mutableMapOf<Int, Float>()
+
+    @FloatRange(from = 0.0, to = 1.0) private var mBlurProgress: Float = 0f
 
     /** Starts the dream content and dream overlay entry animations. */
-    fun startEntryAnimations(view: View) {
-        cancelRunningEntryAnimations()
+    @JvmOverloads
+    fun startEntryAnimations(view: View, animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
+        cancelAnimations()
 
-        mEntryAnimations = AnimatorSet()
-        mEntryAnimations?.apply {
-            playTogether(
-                buildDreamInBlurAnimator(view),
-                buildDreamInTopComplicationsAnimator(),
-                buildDreamInBottomComplicationsAnimator()
-            )
-            doOnEnd { mOverlayStateController.setEntryAnimationsFinished(true) }
-            start()
-        }
+        mAnimator =
+            animatorBuilder().apply {
+                playTogether(
+                    blurAnimator(
+                        view = view,
+                        from = 1f,
+                        to = 0f,
+                        durationMs = mDreamInBlurAnimDurationMs,
+                        delayMs = mDreamInBlurAnimDelayMs
+                    ),
+                    alphaAnimator(
+                        from = 0f,
+                        to = 1f,
+                        durationMs = mDreamInComplicationsAnimDurationMs,
+                        delayMs = mDreamInTopComplicationsAnimDelayMs,
+                        position = ComplicationLayoutParams.POSITION_TOP
+                    ),
+                    alphaAnimator(
+                        from = 0f,
+                        to = 1f,
+                        durationMs = mDreamInComplicationsAnimDurationMs,
+                        delayMs = mDreamInBottomComplicationsAnimDelayMs,
+                        position = ComplicationLayoutParams.POSITION_BOTTOM
+                    )
+                )
+                doOnEnd {
+                    mAnimator = null
+                    mOverlayStateController.setEntryAnimationsFinished(true)
+                }
+                start()
+            }
+    }
+
+    /** Starts the dream content and dream overlay exit animations. */
+    @JvmOverloads
+    fun startExitAnimations(
+        view: View,
+        doneCallback: () -> Unit,
+        animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
+    ) {
+        cancelAnimations()
+
+        mAnimator =
+            animatorBuilder().apply {
+                playTogether(
+                    blurAnimator(
+                        view = view,
+                        // Start the blurring wherever the entry animation ended, in
+                        // case it was cancelled early.
+                        from = mBlurProgress,
+                        to = 1f,
+                        durationMs = mDreamOutBlurDurationMs
+                    ),
+                    translationYAnimator(
+                        from = 0f,
+                        to = mDreamOutTranslationYDistance.toFloat(),
+                        durationMs = mDreamOutTranslationYDurationMs,
+                        delayMs = mDreamOutTranslationYDelayBottomMs,
+                        position = ComplicationLayoutParams.POSITION_BOTTOM,
+                        animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
+                    ),
+                    translationYAnimator(
+                        from = 0f,
+                        to = mDreamOutTranslationYDistance.toFloat(),
+                        durationMs = mDreamOutTranslationYDurationMs,
+                        delayMs = mDreamOutTranslationYDelayTopMs,
+                        position = ComplicationLayoutParams.POSITION_TOP,
+                        animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
+                    ),
+                    alphaAnimator(
+                        from =
+                            mCurrentAlphaAtPosition.getOrDefault(
+                                key = ComplicationLayoutParams.POSITION_BOTTOM,
+                                defaultValue = 1f
+                            ),
+                        to = 0f,
+                        durationMs = mDreamOutAlphaDurationMs,
+                        delayMs = mDreamOutAlphaDelayBottomMs,
+                        position = ComplicationLayoutParams.POSITION_BOTTOM
+                    ),
+                    alphaAnimator(
+                        from =
+                            mCurrentAlphaAtPosition.getOrDefault(
+                                key = ComplicationLayoutParams.POSITION_TOP,
+                                defaultValue = 1f
+                            ),
+                        to = 0f,
+                        durationMs = mDreamOutAlphaDurationMs,
+                        delayMs = mDreamOutAlphaDelayTopMs,
+                        position = ComplicationLayoutParams.POSITION_TOP
+                    )
+                )
+                doOnEnd {
+                    mAnimator = null
+                    mOverlayStateController.setExitAnimationsRunning(false)
+                    doneCallback()
+                }
+                start()
+            }
+        mOverlayStateController.setExitAnimationsRunning(true)
     }
 
     /** Cancels the dream content and dream overlay animations, if they're currently running. */
-    fun cancelRunningEntryAnimations() {
-        if (mEntryAnimations?.isRunning == true) {
-            mEntryAnimations?.cancel()
-        }
-        mEntryAnimations = null
+    fun cancelAnimations() {
+        mAnimator =
+            mAnimator?.let {
+                it.cancel()
+                null
+            }
     }
 
-    private fun buildDreamInBlurAnimator(view: View): Animator {
-        return ValueAnimator.ofFloat(1f, 0f).apply {
-            duration = mDreamInBlurAnimDuration.toLong()
-            startDelay = mDreamInBlurAnimDelay.toLong()
+    private fun blurAnimator(
+        view: View,
+        from: Float,
+        to: Float,
+        durationMs: Long,
+        delayMs: Long = 0
+    ): Animator {
+        return ValueAnimator.ofFloat(from, to).apply {
+            duration = durationMs
+            startDelay = delayMs
             interpolator = Interpolators.LINEAR
             addUpdateListener { animator: ValueAnimator ->
+                mBlurProgress = animator.animatedValue as Float
                 mBlurUtils.applyBlur(
-                    view.viewRootImpl,
-                    mBlurUtils.blurRadiusOfRatio(animator.animatedValue as Float).toInt(),
-                    false /*opaque*/
+                    viewRootImpl = view.viewRootImpl,
+                    radius = mBlurUtils.blurRadiusOfRatio(mBlurProgress).toInt(),
+                    opaque = false
                 )
             }
         }
     }
 
-    private fun buildDreamInTopComplicationsAnimator(): Animator {
-        return ValueAnimator.ofFloat(0f, 1f).apply {
-            duration = mDreamInComplicationsAnimDuration.toLong()
-            startDelay = mDreamInTopComplicationsAnimDelay.toLong()
+    private fun alphaAnimator(
+        from: Float,
+        to: Float,
+        durationMs: Long,
+        delayMs: Long,
+        @Position position: Int
+    ): Animator {
+        return ValueAnimator.ofFloat(from, to).apply {
+            duration = durationMs
+            startDelay = delayMs
             interpolator = Interpolators.LINEAR
             addUpdateListener { va: ValueAnimator ->
-                setTopElementsAlpha(va.animatedValue as Float)
+                setElementsAlphaAtPosition(
+                    alpha = va.animatedValue as Float,
+                    position = position,
+                    fadingOut = to < from
+                )
             }
         }
     }
 
-    private fun buildDreamInBottomComplicationsAnimator(): Animator {
-        return ValueAnimator.ofFloat(0f, 1f).apply {
-            duration = mDreamInComplicationsAnimDuration.toLong()
-            startDelay = mDreamInBottomComplicationsAnimDelay.toLong()
-            interpolator = Interpolators.LINEAR
+    private fun translationYAnimator(
+        from: Float,
+        to: Float,
+        durationMs: Long,
+        delayMs: Long,
+        @Position position: Int,
+        animInterpolator: Interpolator
+    ): Animator {
+        return ValueAnimator.ofFloat(from, to).apply {
+            duration = durationMs
+            startDelay = delayMs
+            interpolator = animInterpolator
             addUpdateListener { va: ValueAnimator ->
-                setBottomElementsAlpha(va.animatedValue as Float)
+                setElementsTranslationYAtPosition(va.animatedValue as Float, position)
             }
-            addListener(
-                object : AnimatorListenerAdapter() {
-                    override fun onAnimationStart(animation: Animator) {
-                        mComplicationHostViewController
-                            .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
-                            .forEach(Consumer { v: View -> v.visibility = View.VISIBLE })
-                    }
-                }
-            )
         }
     }
 
-    /** Sets alpha of top complications and the status bar. */
-    private fun setTopElementsAlpha(alpha: Float) {
-        mComplicationHostViewController
-            .getViewsAtPosition(ComplicationLayoutParams.POSITION_TOP)
-            .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
-        mStatusBarViewController.setAlpha(alpha)
-    }
-
-    /** Sets alpha of bottom complications. */
-    private fun setBottomElementsAlpha(alpha: Float) {
-        mComplicationHostViewController
-            .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
-            .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
-    }
-
-    private fun setAlphaAndEnsureVisible(view: View, alpha: Float) {
-        if (alpha > 0 && view.visibility != View.VISIBLE) {
-            view.visibility = View.VISIBLE
+    /** Sets alpha of complications at the specified position. */
+    private fun setElementsAlphaAtPosition(alpha: Float, position: Int, fadingOut: Boolean) {
+        mCurrentAlphaAtPosition[position] = alpha
+        mComplicationHostViewController.getViewsAtPosition(position).forEach { view ->
+            if (fadingOut) {
+                CrossFadeHelper.fadeOut(view, 1 - alpha, /* remap= */ false)
+            } else {
+                CrossFadeHelper.fadeIn(view, alpha, /* remap= */ false)
+            }
         }
+        if (position == ComplicationLayoutParams.POSITION_TOP) {
+            mStatusBarViewController.setFadeAmount(alpha, fadingOut)
+        }
+    }
 
-        view.alpha = alpha
+    /** Sets y translation of complications at the specified position. */
+    private fun setElementsTranslationYAtPosition(translationY: Float, position: Int) {
+        mComplicationHostViewController.getViewsAtPosition(position).forEach { v ->
+            v.translationY = translationY
+        }
+        if (position == ComplicationLayoutParams.POSITION_TOP) {
+            mStatusBarViewController.setTranslationY(translationY)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 5c6d248..9d7ad30 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -29,6 +29,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -42,6 +44,7 @@
 import com.android.systemui.util.ViewController;
 
 import java.util.Arrays;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -194,7 +197,7 @@
         }
         mPrimaryBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
 
-        mDreamOverlayAnimationsController.cancelRunningEntryAnimations();
+        mDreamOverlayAnimationsController.cancelAnimations();
     }
 
     View getContainerView() {
@@ -251,4 +254,17 @@
                         : aboutToShowBouncerProgress(expansion + 0.03f));
         return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction);
     }
+
+    /**
+     * Handle the dream waking up and run any necessary animations.
+     *
+     * @param onAnimationEnd Callback to trigger once animations are finished.
+     * @param callbackExecutor Executor to execute the callback on.
+     */
+    public void wakeUp(@NonNull Runnable onAnimationEnd, @NonNull Executor callbackExecutor) {
+        mDreamOverlayAnimationsController.startExitAnimations(mView, () -> {
+            callbackExecutor.execute(onAnimationEnd);
+            return null;
+        });
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 8542412..e76d5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -213,6 +213,15 @@
         mLifecycleRegistry.setCurrentState(state);
     }
 
+    @Override
+    public void onWakeUp(@NonNull Runnable onCompletedCallback) {
+        mExecutor.execute(() -> {
+            if (mDreamOverlayContainerViewController != null) {
+                mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+            }
+        });
+    }
+
     /**
      * Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
      * called from the main executing thread. The window attributes closely mirror those that are
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index e80d0be..5f942b6 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -52,6 +52,7 @@
     public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
     public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
     public static final int STATE_DREAM_ENTRY_ANIMATIONS_FINISHED = 1 << 2;
+    public static final int STATE_DREAM_EXIT_ANIMATIONS_RUNNING = 1 << 3;
 
     private static final int OP_CLEAR_STATE = 1;
     private static final int OP_SET_STATE = 2;
@@ -211,6 +212,14 @@
         return containsState(STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
     }
 
+    /**
+     * Returns whether the dream content and dream overlay exit animations are running.
+     * @return {@code true} if animations are running, {@code false} otherwise.
+     */
+    public boolean areExitAnimationsRunning() {
+        return containsState(STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
+    }
+
     private boolean containsState(int state) {
         return (mState & state) != 0;
     }
@@ -257,6 +266,15 @@
     }
 
     /**
+     * Sets whether dream content and dream overlay exit animations are running.
+     * @param running {@code true} if exit animations are running, {@code false} otherwise.
+     */
+    public void setExitAnimationsRunning(boolean running) {
+        modifyState(running ? OP_SET_STATE : OP_CLEAR_STATE,
+                STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
+    }
+
+    /**
      * Returns the available complication types.
      */
     @Complication.ComplicationType
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index d17fbe3..f1bb156 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -37,6 +37,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -217,18 +218,29 @@
     }
 
     /**
-     * Sets alpha of the dream overlay status bar.
+     * Sets fade of the dream overlay status bar.
      *
      * No-op if the dream overlay status bar should not be shown.
      */
-    protected void setAlpha(float alpha) {
+    protected void setFadeAmount(float fadeAmount, boolean fadingOut) {
         updateVisibility();
 
         if (mView.getVisibility() != View.VISIBLE) {
             return;
         }
 
-        mView.setAlpha(alpha);
+        if (fadingOut) {
+            CrossFadeHelper.fadeOut(mView, 1 - fadeAmount, /* remap= */ false);
+        } else {
+            CrossFadeHelper.fadeIn(mView, fadeAmount, /* remap= */ false);
+        }
+    }
+
+    /**
+     * Sets the y translation of the dream overlay status bar.
+     */
+    public void setTranslationY(float translationY) {
+        mView.setTranslationY(translationY);
     }
 
     private boolean shouldShowStatusBar() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
index 41f5578..b07efdf 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
@@ -197,11 +197,11 @@
      */
     interface VisibilityController {
         /**
-         * Called to set the visibility of all shown and future complications.
+         * Called to set the visibility of all shown and future complications. Changes in visibility
+         * will always be animated.
          * @param visibility The desired future visibility.
-         * @param animate whether the change should be animated.
          */
-        void setVisibility(@View.Visibility int visibility, boolean animate);
+        void setVisibility(@View.Visibility int visibility);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
index 5694f6d..48159ae 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
@@ -21,12 +21,9 @@
 import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATION_MARGIN_DEFAULT;
 import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.SCOPED_COMPLICATIONS_LAYOUT;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
 
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.constraintlayout.widget.Constraints;
@@ -34,6 +31,7 @@
 import com.android.systemui.R;
 import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.touch.TouchInsetManager;
 
 import java.util.ArrayList;
@@ -194,7 +192,9 @@
                         break;
                 }
 
-                if (!isRoot) {
+                // Add margin if specified by the complication. Otherwise add default margin
+                // between complications.
+                if (mLayoutParams.isMarginSpecified() || !isRoot) {
                     final int margin = mLayoutParams.getMargin(mDefaultMargin);
                     switch(direction) {
                         case ComplicationLayoutParams.DIRECTION_DOWN:
@@ -479,7 +479,6 @@
     private final TouchInsetManager.TouchInsetSession mSession;
     private final int mFadeInDuration;
     private final int mFadeOutDuration;
-    private ViewPropertyAnimator mViewPropertyAnimator;
 
     /** */
     @Inject
@@ -496,26 +495,16 @@
     }
 
     @Override
-    public void setVisibility(int visibility, boolean animate) {
-        final boolean appearing = visibility == View.VISIBLE;
-
-        if (mViewPropertyAnimator != null) {
-            mViewPropertyAnimator.cancel();
+    public void setVisibility(int visibility) {
+        if (visibility == View.VISIBLE) {
+            CrossFadeHelper.fadeIn(mLayout, mFadeInDuration, /* delay= */ 0);
+        } else {
+            CrossFadeHelper.fadeOut(
+                    mLayout,
+                    mFadeOutDuration,
+                    /* delay= */ 0,
+                    /* endRunnable= */ null);
         }
-
-        if (appearing) {
-            mLayout.setVisibility(View.VISIBLE);
-        }
-
-        mViewPropertyAnimator = mLayout.animate()
-                .alpha(appearing ? 1f : 0f)
-                .setDuration(appearing ? mFadeInDuration : mFadeOutDuration)
-                .setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        mLayout.setVisibility(visibility);
-                    }
-                });
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
index a21eb19..4fae68d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
@@ -38,7 +38,7 @@
             POSITION_START,
     })
 
-    @interface Position {}
+    public @interface Position {}
     /** Align view with the top of parent or bottom of preceding {@link Complication}. */
     public static final int POSITION_TOP = 1 << 0;
     /** Align view with the bottom of parent or top of preceding {@link Complication}. */
@@ -261,6 +261,13 @@
     }
 
     /**
+     * Returns whether margin has been specified by the complication.
+     */
+    public boolean isMarginSpecified() {
+        return mMargin != MARGIN_UNSPECIFIED;
+    }
+
+    /**
      * Returns the margin to apply between complications, or the given default if no margin is
      * specified.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
index cedd850a..c01cf43 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
@@ -33,6 +33,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.animation.ActivityLaunchAnimator;
+import com.android.systemui.controls.ControlsServiceInfo;
 import com.android.systemui.controls.dagger.ControlsComponent;
 import com.android.systemui.controls.management.ControlsListingController;
 import com.android.systemui.controls.ui.ControlsActivity;
@@ -42,6 +43,8 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.util.ViewController;
 
+import java.util.List;
+
 import javax.inject.Inject;
 import javax.inject.Named;
 
@@ -76,16 +79,25 @@
         private final DreamOverlayStateController mDreamOverlayStateController;
         private final ControlsComponent mControlsComponent;
 
-        private boolean mControlServicesAvailable = false;
+        private boolean mOverlayActive = false;
 
         // Callback for when the home controls service availability changes.
         private final ControlsListingController.ControlsListingCallback mControlsCallback =
-                serviceInfos -> {
-                    boolean available = !serviceInfos.isEmpty();
+                services -> updateHomeControlsComplication();
 
-                    if (available != mControlServicesAvailable) {
-                        mControlServicesAvailable = available;
-                        updateComplicationAvailability();
+        private final DreamOverlayStateController.Callback mOverlayStateCallback =
+                new DreamOverlayStateController.Callback() {
+                    @Override
+                    public void onStateChanged() {
+                        if (mOverlayActive == mDreamOverlayStateController.isOverlayActive()) {
+                            return;
+                        }
+
+                        mOverlayActive = !mOverlayActive;
+
+                        if (mOverlayActive) {
+                            updateHomeControlsComplication();
+                        }
                     }
                 };
 
@@ -102,18 +114,29 @@
         public void start() {
             mControlsComponent.getControlsListingController().ifPresent(
                     c -> c.addCallback(mControlsCallback));
+            mDreamOverlayStateController.addCallback(mOverlayStateCallback);
         }
 
-        private void updateComplicationAvailability() {
+        private void updateHomeControlsComplication() {
+            mControlsComponent.getControlsListingController().ifPresent(c -> {
+                if (isHomeControlsAvailable(c.getCurrentServices())) {
+                    mDreamOverlayStateController.addComplication(mComplication);
+                } else {
+                    mDreamOverlayStateController.removeComplication(mComplication);
+                }
+            });
+        }
+
+        private boolean isHomeControlsAvailable(List<ControlsServiceInfo> controlsServices) {
+            if (controlsServices.isEmpty()) {
+                return false;
+            }
+
             final boolean hasFavorites = mControlsComponent.getControlsController()
                     .map(c -> !c.getFavorites().isEmpty())
                     .orElse(false);
-            if (!hasFavorites || !mControlServicesAvailable
-                    || mControlsComponent.getVisibility() == UNAVAILABLE) {
-                mDreamOverlayStateController.removeComplication(mComplication);
-            } else {
-                mDreamOverlayStateController.addComplication(mComplication);
-            }
+            final ControlsComponent.Visibility visibility = mControlsComponent.getVisibility();
+            return hasFavorites && visibility != UNAVAILABLE;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
index c9fecc9..09cc7c5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
@@ -41,6 +41,7 @@
     public static final String COMPLICATIONS_FADE_OUT_DURATION = "complications_fade_out_duration";
     public static final String COMPLICATIONS_FADE_IN_DURATION = "complications_fade_in_duration";
     public static final String COMPLICATIONS_RESTORE_TIMEOUT = "complication_restore_timeout";
+    public static final String COMPLICATIONS_FADE_OUT_DELAY = "complication_fade_out_delay";
 
     /**
      * Generates a {@link ConstraintLayout}, which can host
@@ -75,6 +76,16 @@
     }
 
     /**
+     * Provides the delay to wait for before fading out complications.
+     */
+    @Provides
+    @Named(COMPLICATIONS_FADE_OUT_DELAY)
+    @DreamOverlayComponent.DreamOverlayScope
+    static int providesComplicationsFadeOutDelay(@Main Resources resources) {
+        return resources.getInteger(R.integer.complicationFadeOutDelayMs);
+    }
+
+    /**
      * Provides the fade in duration for complications.
      */
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index 7d2ce51..69b85b5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -48,9 +48,9 @@
 
     int DREAM_CLOCK_TIME_COMPLICATION_WEIGHT = 1;
     int DREAM_SMARTSPACE_COMPLICATION_WEIGHT = 0;
-    int DREAM_MEDIA_COMPLICATION_WEIGHT = -1;
-    int DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT = 1;
-    int DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT = 0;
+    int DREAM_MEDIA_COMPLICATION_WEIGHT = 0;
+    int DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT = 2;
+    int DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT = 1;
 
     /**
      * Provides layout parameters for the clock time complication.
@@ -60,10 +60,11 @@
     static ComplicationLayoutParams provideClockTimeLayoutParams() {
         return new ComplicationLayoutParams(0,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                ComplicationLayoutParams.POSITION_TOP
+                ComplicationLayoutParams.POSITION_BOTTOM
                         | ComplicationLayoutParams.POSITION_START,
-                ComplicationLayoutParams.DIRECTION_DOWN,
-                DREAM_CLOCK_TIME_COMPLICATION_WEIGHT);
+                ComplicationLayoutParams.DIRECTION_UP,
+                DREAM_CLOCK_TIME_COMPLICATION_WEIGHT,
+                0 /*margin*/);
     }
 
     /**
@@ -77,8 +78,10 @@
                 res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height),
                 ComplicationLayoutParams.POSITION_BOTTOM
                         | ComplicationLayoutParams.POSITION_START,
-                ComplicationLayoutParams.DIRECTION_END,
-                DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT);
+                ComplicationLayoutParams.DIRECTION_UP,
+                DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT,
+                // Add margin to the bottom of home controls to horizontally align with smartspace.
+                res.getDimensionPixelSize(R.dimen.dream_overlay_complication_clock_time_padding));
     }
 
     /**
@@ -101,14 +104,13 @@
      */
     @Provides
     @Named(DREAM_SMARTSPACE_LAYOUT_PARAMS)
-    static ComplicationLayoutParams provideSmartspaceLayoutParams() {
+    static ComplicationLayoutParams provideSmartspaceLayoutParams(@Main Resources res) {
         return new ComplicationLayoutParams(0,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                ComplicationLayoutParams.POSITION_TOP
+                ComplicationLayoutParams.POSITION_BOTTOM
                         | ComplicationLayoutParams.POSITION_START,
-                ComplicationLayoutParams.DIRECTION_DOWN,
+                ComplicationLayoutParams.DIRECTION_END,
                 DREAM_SMARTSPACE_COMPLICATION_WEIGHT,
-                0,
-                true /*snapToGuide*/);
+                res.getDimensionPixelSize(R.dimen.dream_overlay_complication_smartspace_padding));
     }
 }
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 f9dca08..101f4a4 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -44,7 +44,7 @@
             DreamOverlayComponent.class,
         })
 public interface DreamModule {
-    String DREAM_ONLY_ENABLED_FOR_SYSTEM_USER = "dream_only_enabled_for_system_user";
+    String DREAM_ONLY_ENABLED_FOR_DOCK_USER = "dream_only_enabled_for_dock_user";
 
     String DREAM_SUPPORTED = "dream_supported";
 
@@ -70,10 +70,10 @@
 
     /** */
     @Provides
-    @Named(DREAM_ONLY_ENABLED_FOR_SYSTEM_USER)
-    static boolean providesDreamOnlyEnabledForSystemUser(@Main Resources resources) {
+    @Named(DREAM_ONLY_ENABLED_FOR_DOCK_USER)
+    static boolean providesDreamOnlyEnabledForDockUser(@Main Resources resources) {
         return resources.getBoolean(
-                com.android.internal.R.bool.config_dreamsOnlyEnabledForSystemUser);
+                com.android.internal.R.bool.config_dreamsOnlyEnabledForDockUser);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index cb012fa..ed0e1d9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -55,6 +55,22 @@
             "dream_in_top_complications_anim_delay";
     public static final String DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY =
             "dream_in_bottom_complications_anim_delay";
+    public static final String DREAM_OUT_TRANSLATION_Y_DISTANCE =
+            "dream_out_complications_translation_y";
+    public static final String DREAM_OUT_TRANSLATION_Y_DURATION =
+            "dream_out_complications_translation_y_duration";
+    public static final String DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM =
+            "dream_out_complications_translation_y_delay_bottom";
+    public static final String DREAM_OUT_TRANSLATION_Y_DELAY_TOP =
+            "dream_out_complications_translation_y_delay_top";
+    public static final String DREAM_OUT_ALPHA_DURATION =
+            "dream_out_complications_alpha_duration";
+    public static final String DREAM_OUT_ALPHA_DELAY_BOTTOM =
+            "dream_out_complications_alpha_delay_bottom";
+    public static final String DREAM_OUT_ALPHA_DELAY_TOP =
+            "dream_out_complications_alpha_delay_top";
+    public static final String DREAM_OUT_BLUR_DURATION =
+            "dream_out_blur_duration";
 
     /** */
     @Provides
@@ -127,8 +143,8 @@
      */
     @Provides
     @Named(DREAM_IN_BLUR_ANIMATION_DURATION)
-    static int providesDreamInBlurAnimationDuration(@Main Resources resources) {
-        return resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
+    static long providesDreamInBlurAnimationDuration(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
     }
 
     /**
@@ -136,8 +152,8 @@
      */
     @Provides
     @Named(DREAM_IN_BLUR_ANIMATION_DELAY)
-    static int providesDreamInBlurAnimationDelay(@Main Resources resources) {
-        return resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
+    static long providesDreamInBlurAnimationDelay(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
     }
 
     /**
@@ -145,8 +161,8 @@
      */
     @Provides
     @Named(DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
-    static int providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
-        return resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
+    static long providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
     }
 
     /**
@@ -154,8 +170,8 @@
      */
     @Provides
     @Named(DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
-    static int providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
-        return resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
+    static long providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
     }
 
     /**
@@ -163,8 +179,69 @@
      */
     @Provides
     @Named(DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
-    static int providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
-        return resources.getInteger(R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
+    static long providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
+        return (long) resources.getInteger(
+                R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
+    }
+
+    /**
+     * Provides the number of pixels to translate complications when waking up from dream.
+     */
+    @Provides
+    @Named(DREAM_OUT_TRANSLATION_Y_DISTANCE)
+    @DreamOverlayComponent.DreamOverlayScope
+    static int providesDreamOutComplicationsTranslationY(@Main Resources resources) {
+        return resources.getDimensionPixelSize(R.dimen.dream_overlay_exit_y_offset);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_TRANSLATION_Y_DURATION)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsTranslationYDuration(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDurationMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsTranslationYDelayBottom(@Main Resources resources) {
+        return (long) resources.getInteger(
+                R.integer.config_dreamOverlayOutTranslationYDelayBottomMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsTranslationYDelayTop(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDelayTopMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_ALPHA_DURATION)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsAlphaDuration(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDurationMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_ALPHA_DELAY_BOTTOM)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsAlphaDelayBottom(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayBottomMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_ALPHA_DELAY_TOP)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutComplicationsAlphaDelayTop(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayTopMs);
+    }
+
+    @Provides
+    @Named(DREAM_OUT_BLUR_DURATION)
+    @DreamOverlayComponent.DreamOverlayScope
+    static long providesDreamOutBlurDuration(@Main Resources resources) {
+        return (long) resources.getInteger(R.integer.config_dreamOverlayOutBlurDurationMs);
     }
 
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
index 3087cdf..e276e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
@@ -16,22 +16,26 @@
 
 package com.android.systemui.dreams.touch;
 
+import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_FADE_OUT_DELAY;
 import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_RESTORE_TIMEOUT;
 
-import android.os.Handler;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.complication.Complication;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.touch.TouchInsetManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
+import java.util.ArrayDeque;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -49,33 +53,58 @@
     private static final String TAG = "HideComplicationHandler";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final Complication.VisibilityController mVisibilityController;
     private final int mRestoreTimeout;
+    private final int mFadeOutDelay;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    private final Handler mHandler;
-    private final Executor mExecutor;
+    private final DelayableExecutor mExecutor;
+    private final DreamOverlayStateController mOverlayStateController;
     private final TouchInsetManager mTouchInsetManager;
+    private final Complication.VisibilityController mVisibilityController;
+    private boolean mHidden = false;
+    @Nullable
+    private Runnable mHiddenCallback;
+    private final ArrayDeque<Runnable> mCancelCallbacks = new ArrayDeque<>();
+
 
     private final Runnable mRestoreComplications = new Runnable() {
         @Override
         public void run() {
-            mVisibilityController.setVisibility(View.VISIBLE, true);
+            mVisibilityController.setVisibility(View.VISIBLE);
+            mHidden = false;
+        }
+    };
+
+    private final Runnable mHideComplications = new Runnable() {
+        @Override
+        public void run() {
+            if (mOverlayStateController.areExitAnimationsRunning()) {
+                // Avoid interfering with the exit animations.
+                return;
+            }
+            mVisibilityController.setVisibility(View.INVISIBLE);
+            mHidden = true;
+            if (mHiddenCallback != null) {
+                mHiddenCallback.run();
+                mHiddenCallback = null;
+            }
         }
     };
 
     @Inject
     HideComplicationTouchHandler(Complication.VisibilityController visibilityController,
             @Named(COMPLICATIONS_RESTORE_TIMEOUT) int restoreTimeout,
+            @Named(COMPLICATIONS_FADE_OUT_DELAY) int fadeOutDelay,
             TouchInsetManager touchInsetManager,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
-            @Main Executor executor,
-            @Main Handler handler) {
+            @Main DelayableExecutor executor,
+            DreamOverlayStateController overlayStateController) {
         mVisibilityController = visibilityController;
         mRestoreTimeout = restoreTimeout;
+        mFadeOutDelay = fadeOutDelay;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
-        mHandler = handler;
         mTouchInsetManager = touchInsetManager;
         mExecutor = executor;
+        mOverlayStateController = overlayStateController;
     }
 
     @Override
@@ -87,7 +116,8 @@
         final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
 
         // If other sessions are interested in this touch, do not fade out elements.
-        if (session.getActiveSessionCount() > 1 || bouncerShowing) {
+        if (session.getActiveSessionCount() > 1 || bouncerShowing
+                || mOverlayStateController.areExitAnimationsRunning()) {
             if (DEBUG) {
                 Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount()
                         + ". Bouncer showing: " + bouncerShowing);
@@ -115,8 +145,11 @@
                 touchCheck.addListener(() -> {
                     try {
                         if (!touchCheck.get()) {
-                            mHandler.removeCallbacks(mRestoreComplications);
-                            mVisibilityController.setVisibility(View.INVISIBLE, true);
+                            // Cancel all pending callbacks.
+                            while (!mCancelCallbacks.isEmpty()) mCancelCallbacks.pop().run();
+                            mCancelCallbacks.add(
+                                    mExecutor.executeDelayed(
+                                            mHideComplications, mFadeOutDelay));
                         } else {
                             // If a touch occurred inside the dream overlay touch insets, do not
                             // handle the touch.
@@ -130,7 +163,23 @@
                     || motionEvent.getAction() == MotionEvent.ACTION_UP) {
                 // End session and initiate delayed reappearance of the complications.
                 session.pop();
-                mHandler.postDelayed(mRestoreComplications, mRestoreTimeout);
+                runAfterHidden(() -> mCancelCallbacks.add(
+                        mExecutor.executeDelayed(mRestoreComplications,
+                                mRestoreTimeout)));
+            }
+        });
+    }
+
+    /**
+     * Triggers a runnable after complications have been hidden. Will override any previously set
+     * runnable currently waiting for hide to happen.
+     */
+    private void runAfterHidden(Runnable runnable) {
+        mExecutor.execute(() -> {
+            if (mHidden) {
+                runnable.run();
+            } else {
+                mHiddenCallback = runnable;
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index ec3fdec..5dae0a2 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -336,7 +336,6 @@
             Log.i(TAG, "Android Restart Suppressed");
             return;
         }
-        Log.i(TAG, "Restarting Android");
         mRestarter.restart();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
new file mode 100644
index 0000000..3d9f627
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.util.Log
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import javax.inject.Inject
+
+/** Restarts SystemUI when the screen is locked. */
+class FeatureFlagsDebugRestarter
+@Inject
+constructor(
+    private val wakefulnessLifecycle: WakefulnessLifecycle,
+    private val systemExitRestarter: SystemExitRestarter,
+) : Restarter {
+
+    val observer =
+        object : WakefulnessLifecycle.Observer {
+            override fun onFinishedGoingToSleep() {
+                Log.d(FeatureFlagsDebug.TAG, "Restarting due to systemui flag change")
+                restartNow()
+            }
+        }
+
+    override fun restart() {
+        Log.d(FeatureFlagsDebug.TAG, "Restart requested. Restarting on next screen off.")
+        if (wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP) {
+            restartNow()
+        } else {
+            wakefulnessLifecycle.addObserver(observer)
+        }
+    }
+
+    private fun restartNow() {
+        systemExitRestarter.restart()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
new file mode 100644
index 0000000..a3f0f66
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.util.Log
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+
+/** Restarts SystemUI when the device appears idle. */
+class FeatureFlagsReleaseRestarter
+@Inject
+constructor(
+    private val wakefulnessLifecycle: WakefulnessLifecycle,
+    private val batteryController: BatteryController,
+    @Background private val bgExecutor: DelayableExecutor,
+    private val systemExitRestarter: SystemExitRestarter
+) : Restarter {
+    var shouldRestart = false
+    var pendingRestart: Runnable? = null
+
+    val observer =
+        object : WakefulnessLifecycle.Observer {
+            override fun onFinishedGoingToSleep() {
+                maybeScheduleRestart()
+            }
+        }
+
+    val batteryCallback =
+        object : BatteryController.BatteryStateChangeCallback {
+            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+                maybeScheduleRestart()
+            }
+        }
+
+    override fun restart() {
+        Log.d(FeatureFlagsDebug.TAG, "Restart requested. Restarting when plugged in and idle.")
+        if (!shouldRestart) {
+            // Don't bother scheduling twice.
+            shouldRestart = true
+            wakefulnessLifecycle.addObserver(observer)
+            batteryController.addCallback(batteryCallback)
+            maybeScheduleRestart()
+        }
+    }
+
+    private fun maybeScheduleRestart() {
+        if (
+            wakefulnessLifecycle.wakefulness == WAKEFULNESS_ASLEEP && batteryController.isPluggedIn
+        ) {
+            if (pendingRestart == null) {
+                pendingRestart = bgExecutor.executeDelayed(this::restartNow, 30L, TimeUnit.SECONDS)
+            }
+        } else if (pendingRestart != null) {
+            pendingRestart?.run()
+            pendingRestart = null
+        }
+    }
+
+    private fun restartNow() {
+        Log.d(FeatureFlagsRelease.TAG, "Restarting due to systemui flag change")
+        systemExitRestarter.restart()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 99dfefa..60fca2d 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -79,10 +79,19 @@
     val NOTIFICATION_GROUP_CORNER =
         unreleasedFlag(116, "notification_group_corner", teamfood = true)
 
+    // TODO(b/259217907)
+    @JvmField
+    val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
+        unreleasedFlag(259217907, "notification_group_dismissal_animation", teamfood = true)
+
     // TODO(b/257506350): Tracking Bug
     val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
 
-    // next id: 118
+    // TODO(b/257315550): Tracking Bug
+    val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when")
+
+    val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
+        unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true)
 
     // 200 - keyguard/lockscreen
     // ** Flag retired **
@@ -112,28 +121,6 @@
     @JvmField val MODERN_BOUNCER = releasedFlag(208, "modern_bouncer")
 
     /**
-     * Whether the user interactor and repository should use `UserSwitcherController`.
-     *
-     * If this is `false`, the interactor and repo skip the controller and directly access the
-     * framework APIs.
-     */
-    // TODO(b/254513286): Tracking Bug
-    val USER_INTERACTOR_AND_REPO_USE_CONTROLLER =
-        unreleasedFlag(210, "user_interactor_and_repo_use_controller")
-
-    /**
-     * Whether `UserSwitcherController` should use the user interactor.
-     *
-     * When this is `true`, the controller does not directly access framework APIs. Instead, it goes
-     * through the interactor.
-     *
-     * Note: do not set this to true if [.USER_INTERACTOR_AND_REPO_USE_CONTROLLER] is `true` as it
-     * would created a cycle between controller -> interactor -> controller.
-     */
-    // TODO(b/254513102): Tracking Bug
-    val USER_CONTROLLER_USES_INTERACTOR = releasedFlag(211, "user_controller_uses_interactor")
-
-    /**
      * Whether the clock on a wide lock screen should use the new "stepping" animation for moving
      * the digits when the clock moves.
      */
@@ -146,20 +133,26 @@
     // TODO(b/255607168): Tracking Bug
     @JvmField val DOZING_MIGRATION_1 = unreleasedFlag(213, "dozing_migration_1")
 
+    // TODO(b/252897742): Tracking Bug
     @JvmField val NEW_ELLIPSE_DETECTION = unreleasedFlag(214, "new_ellipse_detection")
 
+    // TODO(b/252897742): Tracking Bug
     @JvmField val NEW_UDFPS_OVERLAY = unreleasedFlag(215, "new_udfps_overlay")
 
     /**
      * Whether to enable the code powering customizable lock screen quick affordances.
      *
-     * Note that this flag does not enable individual implementations of quick affordances like the
-     * new camera quick affordance. Look for individual flags for those.
+     * This flag enables any new prebuilt quick affordances as well.
      */
+    // TODO(b/255618149): Tracking Bug
     @JvmField
     val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES =
         unreleasedFlag(216, "customizable_lock_screen_quick_affordances", teamfood = false)
 
+    /** Shows chipbar UI whenever the device is unlocked by ActiveUnlock (watch). */
+    // TODO(b/240196500): Tracking Bug
+    @JvmField val ACTIVE_UNLOCK_CHIPBAR = unreleasedFlag(217, "active_unlock_chipbar")
+
     // 300 - power menu
     // TODO(b/254512600): Tracking Bug
     @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -233,6 +226,9 @@
     // TODO(b/256613548): Tracking Bug
     val NEW_STATUS_BAR_WIFI_ICON_BACKEND = unreleasedFlag(609, "new_status_bar_wifi_icon_backend")
 
+    // TODO(b/256623670): Tracking Bug
+    @JvmField val BATTERY_SHIELD_ICON = unreleasedFlag(610, "battery_shield_icon")
+
     // 700 - dialer/calls
     // TODO(b/254512734): Tracking Bug
     val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
@@ -285,6 +281,8 @@
     // TODO(b/254513168): Tracking Bug
     @JvmField val UMO_SURFACE_RIPPLE = unreleasedFlag(907, "umo_surface_ripple")
 
+    @JvmField val MEDIA_FALSING_PENALTY = unreleasedFlag(908, "media_falsing_media")
+
     // 1000 - dock
     val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
 
@@ -368,13 +366,12 @@
 
     // 1300 - screenshots
     // TODO(b/254512719): Tracking Bug
-    @JvmField
-    val SCREENSHOT_REQUEST_PROCESSOR =
-        unreleasedFlag(1300, "screenshot_request_processor", teamfood = true)
+    @JvmField val SCREENSHOT_REQUEST_PROCESSOR = releasedFlag(1300, "screenshot_request_processor")
 
     // TODO(b/254513155): Tracking Bug
     @JvmField
-    val SCREENSHOT_WORK_PROFILE_POLICY = unreleasedFlag(1301, "screenshot_work_profile_policy")
+    val SCREENSHOT_WORK_PROFILE_POLICY =
+        unreleasedFlag(1301, "screenshot_work_profile_policy", teamfood = true)
 
     // 1400 - columbus
     // TODO(b/254512756): Tracking Bug
@@ -390,9 +387,7 @@
         unreleasedFlag(1600, "a11y_floating_menu_fling_spring_animations")
 
     // 1700 - clipboard
-    @JvmField
-    val CLIPBOARD_OVERLAY_REFACTOR =
-        unreleasedFlag(1700, "clipboard_overlay_refactor", teamfood = true)
+    @JvmField val CLIPBOARD_OVERLAY_REFACTOR = releasedFlag(1700, "clipboard_overlay_refactor")
     @JvmField val CLIPBOARD_REMOTE_BEHAVIOR = unreleasedFlag(1701, "clipboard_remote_behavior")
 
     // 1800 - shade container
@@ -408,4 +403,10 @@
 
     // 2100 - Falsing Manager
     @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps")
+
+    // 2200 - udfps
+    // TODO(b/259264861): Tracking Bug
+    @JvmField val UDFPS_NEW_TOUCH_DETECTION = unreleasedFlag(2200, "udfps_new_touch_detection")
+    @JvmField val UDFPS_ELLIPSE_DEBUG_UI = unreleasedFlag(2201, "udfps_ellipse_debug")
+    @JvmField val UDFPS_ELLIPSE_DETECTION = unreleasedFlag(2202, "udfps_ellipse_detection")
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
index 18d7bcf..8442230 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
@@ -15,7 +15,6 @@
  */
 package com.android.systemui.flags
 
-import com.android.internal.statusbar.IStatusBarService
 import dagger.Module
 import dagger.Provides
 import javax.inject.Named
@@ -32,15 +31,5 @@
         fun providesAllFlags(): Map<Int, Flag<*>> {
             return FlagsFactory.knownFlags.map { it.value.id to it.value }.toMap()
         }
-
-        @JvmStatic
-        @Provides
-        fun providesRestarter(barService: IStatusBarService): Restarter {
-            return object : Restarter {
-                override fun restart() {
-                    barService.restart()
-                }
-            }
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/SystemExitRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/SystemExitRestarter.kt
new file mode 100644
index 0000000..f1b1be4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/SystemExitRestarter.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import javax.inject.Inject
+
+class SystemExitRestarter @Inject constructor() : Restarter {
+    override fun restart() {
+        System.exit(0)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 3ef5499..db2cd91 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -125,6 +125,7 @@
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.scrim.ScrimDrawable;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -201,6 +202,7 @@
     protected final SecureSettings mSecureSettings;
     protected final Resources mResources;
     private final ConfigurationController mConfigurationController;
+    private final UserTracker mUserTracker;
     private final UserManager mUserManager;
     private final TrustManager mTrustManager;
     private final IActivityManager mIActivityManager;
@@ -339,6 +341,7 @@
             @NonNull VibratorHelper vibrator,
             @Main Resources resources,
             ConfigurationController configurationController,
+            UserTracker userTracker,
             KeyguardStateController keyguardStateController,
             UserManager userManager,
             TrustManager trustManager,
@@ -370,6 +373,7 @@
         mSecureSettings = secureSettings;
         mResources = resources;
         mConfigurationController = configurationController;
+        mUserTracker = userTracker;
         mUserManager = userManager;
         mTrustManager = trustManager;
         mIActivityManager = iActivityManager;
@@ -1198,11 +1202,7 @@
     }
 
     protected UserInfo getCurrentUser() {
-        try {
-            return mIActivityManager.getCurrentUser();
-        } catch (RemoteException re) {
-            return null;
-        }
+        return mUserTracker.getUserInfo();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index f84a5e3..9235e10 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -375,7 +375,7 @@
     public static final int INDICATION_TYPE_ALIGNMENT = 4;
     public static final int INDICATION_TYPE_TRANSIENT = 5;
     public static final int INDICATION_TYPE_TRUST = 6;
-    public static final int INDICATION_TYPE_RESTING = 7;
+    public static final int INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE = 7;
     public static final int INDICATION_TYPE_USER_LOCKED = 8;
     public static final int INDICATION_TYPE_REVERSE_CHARGING = 10;
     public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE = 11;
@@ -390,7 +390,7 @@
             INDICATION_TYPE_ALIGNMENT,
             INDICATION_TYPE_TRANSIENT,
             INDICATION_TYPE_TRUST,
-            INDICATION_TYPE_RESTING,
+            INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE,
             INDICATION_TYPE_USER_LOCKED,
             INDICATION_TYPE_REVERSE_CHARGING,
             INDICATION_TYPE_BIOMETRIC_MESSAGE,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt
new file mode 100644
index 0000000..1f1ed00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.content.Context
+import android.content.UriMatcher
+import android.content.pm.ProviderInfo
+import android.database.Cursor
+import android.database.MatrixCursor
+import android.net.Uri
+import android.util.Log
+import com.android.systemui.SystemUIAppComponentFactoryBase
+import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback
+import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract
+import javax.inject.Inject
+
+class KeyguardQuickAffordanceProvider :
+    ContentProvider(), SystemUIAppComponentFactoryBase.ContextInitializer {
+
+    @Inject lateinit var interactor: KeyguardQuickAffordanceInteractor
+
+    private lateinit var contextAvailableCallback: ContextAvailableCallback
+
+    private val uriMatcher =
+        UriMatcher(UriMatcher.NO_MATCH).apply {
+            addURI(
+                Contract.AUTHORITY,
+                Contract.SlotTable.TABLE_NAME,
+                MATCH_CODE_ALL_SLOTS,
+            )
+            addURI(
+                Contract.AUTHORITY,
+                Contract.AffordanceTable.TABLE_NAME,
+                MATCH_CODE_ALL_AFFORDANCES,
+            )
+            addURI(
+                Contract.AUTHORITY,
+                Contract.SelectionTable.TABLE_NAME,
+                MATCH_CODE_ALL_SELECTIONS,
+            )
+            addURI(
+                Contract.AUTHORITY,
+                Contract.FlagsTable.TABLE_NAME,
+                MATCH_CODE_ALL_FLAGS,
+            )
+        }
+
+    override fun onCreate(): Boolean {
+        return true
+    }
+
+    override fun attachInfo(context: Context?, info: ProviderInfo?) {
+        contextAvailableCallback.onContextAvailable(checkNotNull(context))
+        super.attachInfo(context, info)
+    }
+
+    override fun setContextAvailableCallback(callback: ContextAvailableCallback) {
+        contextAvailableCallback = callback
+    }
+
+    override fun getType(uri: Uri): String? {
+        val prefix =
+            when (uriMatcher.match(uri)) {
+                MATCH_CODE_ALL_SLOTS,
+                MATCH_CODE_ALL_AFFORDANCES,
+                MATCH_CODE_ALL_FLAGS,
+                MATCH_CODE_ALL_SELECTIONS -> "vnd.android.cursor.dir/vnd."
+                else -> null
+            }
+
+        val tableName =
+            when (uriMatcher.match(uri)) {
+                MATCH_CODE_ALL_SLOTS -> Contract.SlotTable.TABLE_NAME
+                MATCH_CODE_ALL_AFFORDANCES -> Contract.AffordanceTable.TABLE_NAME
+                MATCH_CODE_ALL_SELECTIONS -> Contract.SelectionTable.TABLE_NAME
+                MATCH_CODE_ALL_FLAGS -> Contract.FlagsTable.TABLE_NAME
+                else -> null
+            }
+
+        if (prefix == null || tableName == null) {
+            return null
+        }
+
+        return "$prefix${Contract.AUTHORITY}.$tableName"
+    }
+
+    override fun insert(uri: Uri, values: ContentValues?): Uri? {
+        if (uriMatcher.match(uri) != MATCH_CODE_ALL_SELECTIONS) {
+            throw UnsupportedOperationException()
+        }
+
+        return insertSelection(values)
+    }
+
+    override fun query(
+        uri: Uri,
+        projection: Array<out String>?,
+        selection: String?,
+        selectionArgs: Array<out String>?,
+        sortOrder: String?,
+    ): Cursor? {
+        return when (uriMatcher.match(uri)) {
+            MATCH_CODE_ALL_AFFORDANCES -> queryAffordances()
+            MATCH_CODE_ALL_SLOTS -> querySlots()
+            MATCH_CODE_ALL_SELECTIONS -> querySelections()
+            MATCH_CODE_ALL_FLAGS -> queryFlags()
+            else -> null
+        }
+    }
+
+    override fun update(
+        uri: Uri,
+        values: ContentValues?,
+        selection: String?,
+        selectionArgs: Array<out String>?,
+    ): Int {
+        Log.e(TAG, "Update is not supported!")
+        return 0
+    }
+
+    override fun delete(
+        uri: Uri,
+        selection: String?,
+        selectionArgs: Array<out String>?,
+    ): Int {
+        if (uriMatcher.match(uri) != MATCH_CODE_ALL_SELECTIONS) {
+            throw UnsupportedOperationException()
+        }
+
+        return deleteSelection(uri, selectionArgs)
+    }
+
+    private fun insertSelection(values: ContentValues?): Uri? {
+        if (values == null) {
+            throw IllegalArgumentException("Cannot insert selection, no values passed in!")
+        }
+
+        if (!values.containsKey(Contract.SelectionTable.Columns.SLOT_ID)) {
+            throw IllegalArgumentException(
+                "Cannot insert selection, " +
+                    "\"${Contract.SelectionTable.Columns.SLOT_ID}\" not specified!"
+            )
+        }
+
+        if (!values.containsKey(Contract.SelectionTable.Columns.AFFORDANCE_ID)) {
+            throw IllegalArgumentException(
+                "Cannot insert selection, " +
+                    "\"${Contract.SelectionTable.Columns.AFFORDANCE_ID}\" not specified!"
+            )
+        }
+
+        val slotId = values.getAsString(Contract.SelectionTable.Columns.SLOT_ID)
+        val affordanceId = values.getAsString(Contract.SelectionTable.Columns.AFFORDANCE_ID)
+
+        if (slotId.isNullOrEmpty()) {
+            throw IllegalArgumentException("Cannot insert selection, slot ID was empty!")
+        }
+
+        if (affordanceId.isNullOrEmpty()) {
+            throw IllegalArgumentException("Cannot insert selection, affordance ID was empty!")
+        }
+
+        val success =
+            interactor.select(
+                slotId = slotId,
+                affordanceId = affordanceId,
+            )
+
+        return if (success) {
+            Log.d(TAG, "Successfully selected $affordanceId for slot $slotId")
+            context?.contentResolver?.notifyChange(Contract.SelectionTable.URI, null)
+            Contract.SelectionTable.URI
+        } else {
+            Log.d(TAG, "Failed to select $affordanceId for slot $slotId")
+            null
+        }
+    }
+
+    private fun querySelections(): Cursor {
+        return MatrixCursor(
+                arrayOf(
+                    Contract.SelectionTable.Columns.SLOT_ID,
+                    Contract.SelectionTable.Columns.AFFORDANCE_ID,
+                )
+            )
+            .apply {
+                val affordanceIdsBySlotId = interactor.getSelections()
+                affordanceIdsBySlotId.entries.forEach { (slotId, affordanceIds) ->
+                    affordanceIds.forEach { affordanceId ->
+                        addRow(
+                            arrayOf(
+                                slotId,
+                                affordanceId,
+                            )
+                        )
+                    }
+                }
+            }
+    }
+
+    private fun queryAffordances(): Cursor {
+        return MatrixCursor(
+                arrayOf(
+                    Contract.AffordanceTable.Columns.ID,
+                    Contract.AffordanceTable.Columns.NAME,
+                    Contract.AffordanceTable.Columns.ICON,
+                )
+            )
+            .apply {
+                interactor.getAffordancePickerRepresentations().forEach { representation ->
+                    addRow(
+                        arrayOf(
+                            representation.id,
+                            representation.name,
+                            representation.iconResourceId,
+                        )
+                    )
+                }
+            }
+    }
+
+    private fun querySlots(): Cursor {
+        return MatrixCursor(
+                arrayOf(
+                    Contract.SlotTable.Columns.ID,
+                    Contract.SlotTable.Columns.CAPACITY,
+                )
+            )
+            .apply {
+                interactor.getSlotPickerRepresentations().forEach { representation ->
+                    addRow(
+                        arrayOf(
+                            representation.id,
+                            representation.maxSelectedAffordances,
+                        )
+                    )
+                }
+            }
+    }
+
+    private fun queryFlags(): Cursor {
+        return MatrixCursor(
+                arrayOf(
+                    Contract.FlagsTable.Columns.NAME,
+                    Contract.FlagsTable.Columns.VALUE,
+                )
+            )
+            .apply {
+                interactor.getPickerFlags().forEach { flag ->
+                    addRow(
+                        arrayOf(
+                            flag.name,
+                            if (flag.value) {
+                                1
+                            } else {
+                                0
+                            },
+                        )
+                    )
+                }
+            }
+    }
+
+    private fun deleteSelection(
+        uri: Uri,
+        selectionArgs: Array<out String>?,
+    ): Int {
+        if (selectionArgs == null) {
+            throw IllegalArgumentException(
+                "Cannot delete selection, selection arguments not included!"
+            )
+        }
+
+        val (slotId, affordanceId) =
+            when (selectionArgs.size) {
+                1 -> Pair(selectionArgs[0], null)
+                2 -> Pair(selectionArgs[0], selectionArgs[1])
+                else ->
+                    throw IllegalArgumentException(
+                        "Cannot delete selection, selection arguments has wrong size, expected to" +
+                            " have 1 or 2 arguments, had ${selectionArgs.size} instead!"
+                    )
+            }
+
+        val deleted =
+            interactor.unselect(
+                slotId = slotId,
+                affordanceId = affordanceId,
+            )
+
+        return if (deleted) {
+            Log.d(TAG, "Successfully unselected $affordanceId for slot $slotId")
+            context?.contentResolver?.notifyChange(uri, null)
+            1
+        } else {
+            Log.d(TAG, "Failed to unselect $affordanceId for slot $slotId")
+            0
+        }
+    }
+
+    companion object {
+        private const val TAG = "KeyguardQuickAffordanceProvider"
+        private const val MATCH_CODE_ALL_SLOTS = 1
+        private const val MATCH_CODE_ALL_AFFORDANCES = 2
+        private const val MATCH_CODE_ALL_SELECTIONS = 3
+        private const val MATCH_CODE_ALL_FLAGS = 4
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 2a73797..34ae1a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -17,7 +17,6 @@
 package com.android.systemui.keyguard;
 
 import android.annotation.AnyThread;
-import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -52,6 +51,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUIAppComponentFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -140,6 +140,8 @@
     public KeyguardBypassController mKeyguardBypassController;
     @Inject
     public KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Inject
+    UserTracker mUserTracker;
     private CharSequence mMediaTitle;
     private CharSequence mMediaArtist;
     protected boolean mDozing;
@@ -355,7 +357,7 @@
         synchronized (this) {
             if (withinNHoursLocked(mNextAlarmInfo, ALARM_VISIBILITY_HOURS)) {
                 String pattern = android.text.format.DateFormat.is24HourFormat(getContext(),
-                        ActivityManager.getCurrentUser()) ? "HH:mm" : "h:mm";
+                        mUserTracker.getUserId()) ? "HH:mm" : "h:mm";
                 mNextAlarm = android.text.format.DateFormat.format(pattern,
                         mNextAlarmInfo.getTriggerTime()).toString();
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7cd3843..250317b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -36,7 +36,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -124,6 +123,7 @@
 import com.android.systemui.keyguard.dagger.KeyguardModule;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -263,6 +263,7 @@
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
+    private final UserTracker mUserTracker;
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final Executor mUiBgExecutor;
     private final ScreenOffAnimationController mScreenOffAnimationController;
@@ -409,6 +410,11 @@
     private final int mDreamOpenAnimationDuration;
 
     /**
+     * The duration in milliseconds of the dream close animation.
+     */
+    private final int mDreamCloseAnimationDuration;
+
+    /**
      * The animation used for hiding keyguard. This is used to fetch the animation timings if
      * WindowManager is not providing us with them.
      */
@@ -715,7 +721,7 @@
 
         @Override
         public void keyguardDone(boolean strongAuth, int targetUserId) {
-            if (targetUserId != ActivityManager.getCurrentUser()) {
+            if (targetUserId != mUserTracker.getUserId()) {
                 return;
             }
             if (DEBUG) Log.d(TAG, "keyguardDone");
@@ -738,7 +744,7 @@
         public void keyguardDonePending(boolean strongAuth, int targetUserId) {
             Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardDonePending");
             if (DEBUG) Log.d(TAG, "keyguardDonePending");
-            if (targetUserId != ActivityManager.getCurrentUser()) {
+            if (targetUserId != mUserTracker.getUserId()) {
                 Trace.endSection();
                 return;
             }
@@ -1054,7 +1060,8 @@
                         }
 
                         mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
-                        mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
+                        mUnoccludeAnimator.setDuration(isDream ? mDreamCloseAnimationDuration
+                                : UNOCCLUDE_ANIMATION_DURATION);
                         mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
                         mUnoccludeAnimator.addUpdateListener(
                                 animation -> {
@@ -1130,6 +1137,7 @@
      */
     public KeyguardViewMediator(
             Context context,
+            UserTracker userTracker,
             FalsingCollector falsingCollector,
             LockPatternUtils lockPatternUtils,
             BroadcastDispatcher broadcastDispatcher,
@@ -1155,6 +1163,7 @@
             Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator) {
         mContext = context;
+        mUserTracker = userTracker;
         mFalsingCollector = falsingCollector;
         mLockPatternUtils = lockPatternUtils;
         mBroadcastDispatcher = broadcastDispatcher;
@@ -1204,6 +1213,8 @@
 
         mDreamOpenAnimationDuration = context.getResources().getInteger(
                 com.android.internal.R.integer.config_dreamOpenAnimationDuration);
+        mDreamCloseAnimationDuration = context.getResources().getInteger(
+                com.android.internal.R.integer.config_dreamCloseAnimationDuration);
     }
 
     public void userActivity() {
@@ -1233,7 +1244,7 @@
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
-        KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
+        KeyguardUpdateMonitor.setCurrentUser(mUserTracker.getUserId());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
         // is disabled.
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 78a7c9e..ef3c443 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -47,6 +47,7 @@
 import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
 import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
 import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -86,6 +87,7 @@
     @SysUISingleton
     public static KeyguardViewMediator newKeyguardViewMediator(
             Context context,
+            UserTracker userTracker,
             FalsingCollector falsingCollector,
             LockPatternUtils lockPatternUtils,
             BroadcastDispatcher broadcastDispatcher,
@@ -114,6 +116,7 @@
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator) {
         return new KeyguardViewMediator(
                 context,
+                userTracker,
                 falsingCollector,
                 lockPatternUtils,
                 broadcastDispatcher,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
index a069582..f5220b8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
@@ -24,6 +24,7 @@
  */
 object BuiltInKeyguardQuickAffordanceKeys {
     // Please keep alphabetical order of const names to simplify future maintenance.
+    const val CAMERA = "camera"
     const val HOME_CONTROLS = "home"
     const val QR_CODE_SCANNER = "qr_code_scanner"
     const val QUICK_ACCESS_WALLET = "wallet"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
new file mode 100644
index 0000000..3c09aab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2022 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.app.StatusBarManager
+import android.content.Context
+import com.android.systemui.R
+import com.android.systemui.animation.Expandable
+import com.android.systemui.camera.CameraGestureHelper
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import javax.inject.Inject
+
+@SysUISingleton
+class CameraQuickAffordanceConfig @Inject constructor(
+        @Application private val context: Context,
+        private val cameraGestureHelper: CameraGestureHelper,
+) : KeyguardQuickAffordanceConfig {
+
+    override val key: String
+        get() = BuiltInKeyguardQuickAffordanceKeys.CAMERA
+
+    override val pickerName: String
+        get() = context.getString(R.string.accessibility_camera_button)
+
+    override val pickerIconResourceId: Int
+        get() = com.android.internal.R.drawable.perm_group_camera
+
+    override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
+        get() = flowOf(
+            KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = Icon.Resource(
+                            com.android.internal.R.drawable.perm_group_camera,
+                            ContentDescription.Resource(R.string.accessibility_camera_button)
+                    )
+            )
+        )
+
+    override fun onTriggered(expandable: Expandable?): KeyguardQuickAffordanceConfig.OnTriggeredResult {
+        cameraGestureHelper.launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
index bea9363..f7225a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
@@ -29,8 +29,10 @@
         home: HomeControlsKeyguardQuickAffordanceConfig,
         quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig,
         qrCodeScanner: QrCodeScannerKeyguardQuickAffordanceConfig,
+        camera: CameraQuickAffordanceConfig,
     ): Set<KeyguardQuickAffordanceConfig> {
         return setOf(
+            camera,
             home,
             quickAccessWallet,
             qrCodeScanner,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncer.kt
new file mode 100644
index 0000000..766096f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncer.kt
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.os.UserHandle
+import android.provider.Settings
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer.Companion.BINDINGS
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Keeps quick affordance selections and legacy user settings in sync.
+ *
+ * "Legacy user settings" are user settings like: Settings > Display > Lock screen > "Show device
+ * controls" Settings > Display > Lock screen > "Show wallet"
+ *
+ * Quick affordance selections are the ones available through the new custom lock screen experience
+ * from Settings > Wallpaper & Style.
+ *
+ * This class keeps these in sync, mostly for backwards compatibility purposes and in order to not
+ * "forget" an existing legacy user setting when the device gets updated with a version of System UI
+ * that has the new customizable lock screen feature.
+ *
+ * The way it works is that, when [startSyncing] is called, the syncer starts coroutines to listen
+ * for changes in both legacy user settings and their respective affordance selections. Whenever one
+ * of each pair is changed, the other member of that pair is also updated to match. For example, if
+ * the user turns on "Show device controls", we automatically select the home controls affordance
+ * for the preferred slot. Conversely, when the home controls affordance is unselected by the user,
+ * we set the "Show device controls" setting to "off".
+ *
+ * The class can be configured by updating its list of triplets in the code under [BINDINGS].
+ */
+@SysUISingleton
+class KeyguardQuickAffordanceLegacySettingSyncer
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val secureSettings: SecureSettings,
+    private val selectionsManager: KeyguardQuickAffordanceSelectionManager,
+) {
+    companion object {
+        private val BINDINGS =
+            listOf(
+                Binding(
+                    settingsKey = Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
+                    slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                    affordanceId = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
+                ),
+                Binding(
+                    settingsKey = Settings.Secure.LOCKSCREEN_SHOW_WALLET,
+                    slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                    affordanceId = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
+                ),
+                Binding(
+                    settingsKey = Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER,
+                    slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                    affordanceId = BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER,
+                ),
+            )
+    }
+
+    fun startSyncing(
+        bindings: List<Binding> = BINDINGS,
+    ): Job {
+        return scope.launch { bindings.forEach { binding -> startSyncing(this, binding) } }
+    }
+
+    private fun startSyncing(
+        scope: CoroutineScope,
+        binding: Binding,
+    ) {
+        secureSettings
+            .observerFlow(
+                names = arrayOf(binding.settingsKey),
+                userId = UserHandle.USER_ALL,
+            )
+            .map {
+                isSet(
+                    settingsKey = binding.settingsKey,
+                )
+            }
+            .distinctUntilChanged()
+            .onEach { isSet ->
+                if (isSelected(binding.affordanceId) != isSet) {
+                    if (isSet) {
+                        select(
+                            slotId = binding.slotId,
+                            affordanceId = binding.affordanceId,
+                        )
+                    } else {
+                        unselect(
+                            affordanceId = binding.affordanceId,
+                        )
+                    }
+                }
+            }
+            .flowOn(backgroundDispatcher)
+            .launchIn(scope)
+
+        selectionsManager.selections
+            .map { it.values.flatten().toSet() }
+            .map { it.contains(binding.affordanceId) }
+            .distinctUntilChanged()
+            .onEach { isSelected ->
+                if (isSet(binding.settingsKey) != isSelected) {
+                    set(binding.settingsKey, isSelected)
+                }
+            }
+            .flowOn(backgroundDispatcher)
+            .launchIn(scope)
+    }
+
+    private fun isSelected(
+        affordanceId: String,
+    ): Boolean {
+        return selectionsManager
+            .getSelections() // Map<String, List<String>>
+            .values // Collection<List<String>>
+            .flatten() // List<String>
+            .toSet() // Set<String>
+            .contains(affordanceId)
+    }
+
+    private fun select(
+        slotId: String,
+        affordanceId: String,
+    ) {
+        val affordanceIdsAtSlotId = selectionsManager.getSelections()[slotId] ?: emptyList()
+        selectionsManager.setSelections(
+            slotId = slotId,
+            affordanceIds = affordanceIdsAtSlotId + listOf(affordanceId),
+        )
+    }
+
+    private fun unselect(
+        affordanceId: String,
+    ) {
+        val currentSelections = selectionsManager.getSelections()
+        val slotIdsContainingAffordanceId =
+            currentSelections
+                .filter { (_, affordanceIds) -> affordanceIds.contains(affordanceId) }
+                .map { (slotId, _) -> slotId }
+
+        slotIdsContainingAffordanceId.forEach { slotId ->
+            val currentAffordanceIds = currentSelections[slotId] ?: emptyList()
+            val affordanceIdsAfterUnselecting =
+                currentAffordanceIds.toMutableList().apply { remove(affordanceId) }
+
+            selectionsManager.setSelections(
+                slotId = slotId,
+                affordanceIds = affordanceIdsAfterUnselecting,
+            )
+        }
+    }
+
+    private fun isSet(
+        settingsKey: String,
+    ): Boolean {
+        return secureSettings.getIntForUser(
+            settingsKey,
+            0,
+            UserHandle.USER_CURRENT,
+        ) != 0
+    }
+
+    private suspend fun set(
+        settingsKey: String,
+        isSet: Boolean,
+    ) {
+        withContext(backgroundDispatcher) {
+            secureSettings.putInt(
+                settingsKey,
+                if (isSet) 1 else 0,
+            )
+        }
+    }
+
+    data class Binding(
+        val settingsKey: String,
+        val slotId: String,
+        val affordanceId: String,
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManager.kt
index 9c9354f..b29cf45 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManager.kt
@@ -17,46 +17,138 @@
 
 package com.android.systemui.keyguard.data.quickaffordance
 
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.R
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
 import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flatMapLatest
 
 /**
  * Manages and provides access to the current "selections" of keyguard quick affordances, answering
  * the question "which affordances should the keyguard show?".
  */
 @SysUISingleton
-class KeyguardQuickAffordanceSelectionManager @Inject constructor() {
+class KeyguardQuickAffordanceSelectionManager
+@Inject
+constructor(
+    @Application context: Context,
+    private val userFileManager: UserFileManager,
+    private val userTracker: UserTracker,
+) {
 
-    // TODO(b/254858695): implement a persistence layer (database).
-    private val _selections = MutableStateFlow<Map<String, List<String>>>(emptyMap())
+    private val sharedPrefs: SharedPreferences
+        get() =
+            userFileManager.getSharedPreferences(
+                FILE_NAME,
+                Context.MODE_PRIVATE,
+                userTracker.userId,
+            )
+
+    private val userId: Flow<Int> = conflatedCallbackFlow {
+        val callback =
+            object : UserTracker.Callback {
+                override fun onUserChanged(newUser: Int, userContext: Context) {
+                    trySendWithFailureLogging(newUser, TAG)
+                }
+            }
+
+        userTracker.addCallback(callback) { it.run() }
+        trySendWithFailureLogging(userTracker.userId, TAG)
+
+        awaitClose { userTracker.removeCallback(callback) }
+    }
+    private val defaults: Map<String, List<String>> by lazy {
+        context.resources
+            .getStringArray(R.array.config_keyguardQuickAffordanceDefaults)
+            .associate { item ->
+                val splitUp = item.split(SLOT_AFFORDANCES_DELIMITER)
+                check(splitUp.size == 2)
+                val slotId = splitUp[0]
+                val affordanceIds = splitUp[1].split(AFFORDANCE_DELIMITER)
+                slotId to affordanceIds
+            }
+    }
 
     /** IDs of affordances to show, indexed by slot ID, and sorted in descending priority order. */
-    val selections: Flow<Map<String, List<String>>> = _selections.asStateFlow()
+    val selections: Flow<Map<String, List<String>>> =
+        userId.flatMapLatest {
+            conflatedCallbackFlow {
+                val listener =
+                    SharedPreferences.OnSharedPreferenceChangeListener { _, _ ->
+                        trySend(getSelections())
+                    }
+
+                sharedPrefs.registerOnSharedPreferenceChangeListener(listener)
+                send(getSelections())
+
+                awaitClose { sharedPrefs.unregisterOnSharedPreferenceChangeListener(listener) }
+            }
+        }
 
     /**
      * Returns a snapshot of the IDs of affordances to show, indexed by slot ID, and sorted in
      * descending priority order.
      */
-    suspend fun getSelections(): Map<String, List<String>> {
-        return _selections.value
+    fun getSelections(): Map<String, List<String>> {
+        val slotKeys = sharedPrefs.all.keys.filter { it.startsWith(KEY_PREFIX_SLOT) }
+        val result =
+            slotKeys
+                .associate { key ->
+                    val slotId = key.substring(KEY_PREFIX_SLOT.length)
+                    val value = sharedPrefs.getString(key, null)
+                    val affordanceIds =
+                        if (!value.isNullOrEmpty()) {
+                            value.split(AFFORDANCE_DELIMITER)
+                        } else {
+                            emptyList()
+                        }
+                    slotId to affordanceIds
+                }
+                .toMutableMap()
+
+        // If the result map is missing keys, it means that the system has never set anything for
+        // those slots. This is where we need examine our defaults and see if there should be a
+        // default value for the affordances in the slot IDs that are missing from the result.
+        //
+        // Once the user makes any selection for a slot, even when they select "None", this class
+        // will persist a key for that slot ID. In the case of "None", it will have a value of the
+        // empty string. This is why this system works.
+        defaults.forEach { (slotId, affordanceIds) ->
+            if (!result.containsKey(slotId)) {
+                result[slotId] = affordanceIds
+            }
+        }
+
+        return result
     }
 
     /**
      * Updates the IDs of affordances to show at the slot with the given ID. The order of affordance
      * IDs should be descending priority order.
      */
-    suspend fun setSelections(
+    fun setSelections(
         slotId: String,
         affordanceIds: List<String>,
     ) {
-        // Must make a copy of the map and update it, otherwise, the MutableStateFlow won't emit
-        // when we set its value to the same instance of the original map, even if we change the
-        // map by updating the value of one of its keys.
-        val copy = _selections.value.toMutableMap()
-        copy[slotId] = affordanceIds
-        _selections.value = copy
+        val key = "$KEY_PREFIX_SLOT$slotId"
+        val value = affordanceIds.joinToString(AFFORDANCE_DELIMITER)
+        sharedPrefs.edit().putString(key, value).apply()
+    }
+
+    companion object {
+        private const val TAG = "KeyguardQuickAffordanceSelectionManager"
+        @VisibleForTesting const val FILE_NAME = "quick_affordance_selections"
+        private const val KEY_PREFIX_SLOT = "slot_"
+        private const val SLOT_AFFORDANCES_DELIMITER = ":"
+        private const val AFFORDANCE_DELIMITER = ","
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index d4514c5..9a90fe7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -16,16 +16,17 @@
 
 package com.android.systemui.keyguard.data.repository
 
-import android.hardware.biometrics.BiometricSourceType
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.keyguard.ViewMediatorCallback
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
 import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import com.android.systemui.statusbar.phone.KeyguardBouncer
 import javax.inject.Inject
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 
 /** Encapsulates app state for the lock screen primary and alternate bouncer. */
@@ -70,33 +71,19 @@
     private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
     /** Determines if user is already unlocked */
     val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
-
-    var bouncerPromptReason: Int? = null
-    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
-    val showMessage = _showMessage.asStateFlow()
+    private val _showMessage =
+        MutableSharedFlow<BouncerShowMessageModel?>(
+            replay = 1,
+            onBufferOverflow = BufferOverflow.DROP_OLDEST
+        )
+    val showMessage = _showMessage.asSharedFlow()
     private val _resourceUpdateRequests = MutableStateFlow(false)
     val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
-
+    val bouncerPromptReason: Int
+        get() = viewMediatorCallback.bouncerPromptReason
     val bouncerErrorMessage: CharSequence?
         get() = viewMediatorCallback.consumeCustomMessage()
 
-    init {
-        val callback =
-            object : KeyguardUpdateMonitorCallback() {
-                override fun onStrongAuthStateChanged(userId: Int) {
-                    bouncerPromptReason = viewMediatorCallback.bouncerPromptReason
-                }
-
-                override fun onLockedOutStateChanged(type: BiometricSourceType) {
-                    if (type == BiometricSourceType.FINGERPRINT) {
-                        bouncerPromptReason = viewMediatorCallback.bouncerPromptReason
-                    }
-                }
-            }
-
-        keyguardUpdateMonitor.registerCallback(callback)
-    }
-
     fun setPrimaryScrimmed(isScrimmed: Boolean) {
         _primaryBouncerScrimmed.value = isScrimmed
     }
@@ -138,7 +125,7 @@
     }
 
     fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
-        _showMessage.value = bouncerShowMessageModel
+        _showMessage.tryEmit(bouncerShowMessageModel)
     }
 
     fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index 95f614f..533b3ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -17,31 +17,31 @@
 
 package com.android.systemui.keyguard.data.repository
 
+import android.content.Context
+import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
-import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
 
 /** Abstracts access to application state related to keyguard quick affordances. */
 @SysUISingleton
 class KeyguardQuickAffordanceRepository
 @Inject
 constructor(
+    @Application private val appContext: Context,
     @Application private val scope: CoroutineScope,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val selectionManager: KeyguardQuickAffordanceSelectionManager,
+    legacySettingSyncer: KeyguardQuickAffordanceLegacySettingSyncer,
     private val configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
 ) {
     /**
@@ -61,11 +61,39 @@
                 initialValue = emptyMap(),
             )
 
+    private val _slotPickerRepresentations: List<KeyguardSlotPickerRepresentation> by lazy {
+        fun parseSlot(unparsedSlot: String): Pair<String, Int> {
+            val split = unparsedSlot.split(SLOT_CONFIG_DELIMITER)
+            check(split.size == 2)
+            val slotId = split[0]
+            val slotCapacity = split[1].toInt()
+            return slotId to slotCapacity
+        }
+
+        val unparsedSlots =
+            appContext.resources.getStringArray(R.array.config_keyguardQuickAffordanceSlots)
+
+        val seenSlotIds = mutableSetOf<String>()
+        unparsedSlots.mapNotNull { unparsedSlot ->
+            val (slotId, slotCapacity) = parseSlot(unparsedSlot)
+            check(!seenSlotIds.contains(slotId)) { "Duplicate slot \"$slotId\"!" }
+            seenSlotIds.add(slotId)
+            KeyguardSlotPickerRepresentation(
+                id = slotId,
+                maxSelectedAffordances = slotCapacity,
+            )
+        }
+    }
+
+    init {
+        legacySettingSyncer.startSyncing()
+    }
+
     /**
      * Returns a snapshot of the [KeyguardQuickAffordanceConfig] instances of the affordances at the
      * slot with the given ID. The configs are sorted in descending priority order.
      */
-    suspend fun getSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
+    fun getSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
         val selections = selectionManager.getSelections().getOrDefault(slotId, emptyList())
         return configs.filter { selections.contains(it.key) }
     }
@@ -74,7 +102,7 @@
      * Returns a snapshot of the IDs of the selected affordances, indexed by slot ID. The configs
      * are sorted in descending priority order.
      */
-    suspend fun getSelections(): Map<String, List<String>> {
+    fun getSelections(): Map<String, List<String>> {
         return selectionManager.getSelections()
     }
 
@@ -86,12 +114,10 @@
         slotId: String,
         affordanceIds: List<String>,
     ) {
-        scope.launch(backgroundDispatcher) {
-            selectionManager.setSelections(
-                slotId = slotId,
-                affordanceIds = affordanceIds,
-            )
-        }
+        selectionManager.setSelections(
+            slotId = slotId,
+            affordanceIds = affordanceIds,
+        )
     }
 
     /**
@@ -115,14 +141,10 @@
      * each slot and select which affordance(s) is/are installed in each slot on the keyguard.
      */
     fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> {
-        // TODO(b/256195304): source these from a config XML file.
-        return listOf(
-            KeyguardSlotPickerRepresentation(
-                id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
-            ),
-            KeyguardSlotPickerRepresentation(
-                id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
-            ),
-        )
+        return _slotPickerRepresentations
+    }
+
+    companion object {
+        private const val SLOT_CONFIG_DELIMITER = ":"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index ca25282..9d5d8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.data.repository
 
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.common.shared.model.Position
@@ -69,6 +70,9 @@
      */
     val isKeyguardShowing: Flow<Boolean>
 
+    /** Observable for the signal that keyguard is about to go away. */
+    val isKeyguardGoingAway: Flow<Boolean>
+
     /** Observable for whether the bouncer is showing. */
     val isBouncerShowing: Flow<Boolean>
 
@@ -85,6 +89,14 @@
     val isDozing: Flow<Boolean>
 
     /**
+     * Observable for whether the device is dreaming.
+     *
+     * Dozing/AOD is a specific type of dream, but it is also possible for other non-systemui dreams
+     * to be active, such as screensavers.
+     */
+    val isDreaming: Flow<Boolean>
+
+    /**
      * Observable for the amount of doze we are currently in.
      *
      * While in doze state, this amount can change - driving a cycle of animations designed to avoid
@@ -136,12 +148,12 @@
 class KeyguardRepositoryImpl
 @Inject
 constructor(
-        statusBarStateController: StatusBarStateController,
-        dozeHost: DozeHost,
-        wakefulnessLifecycle: WakefulnessLifecycle,
-        biometricUnlockController: BiometricUnlockController,
-        private val keyguardStateController: KeyguardStateController,
-        private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+    statusBarStateController: StatusBarStateController,
+    dozeHost: DozeHost,
+    wakefulnessLifecycle: WakefulnessLifecycle,
+    biometricUnlockController: BiometricUnlockController,
+    private val keyguardStateController: KeyguardStateController,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
 ) : KeyguardRepository {
     private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
     override val animateBottomAreaDozingTransitions =
@@ -176,6 +188,29 @@
         awaitClose { keyguardStateController.removeCallback(callback) }
     }
 
+    override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
+        val callback =
+            object : KeyguardStateController.Callback {
+                override fun onKeyguardGoingAwayChanged() {
+                    trySendWithFailureLogging(
+                        keyguardStateController.isKeyguardGoingAway,
+                        TAG,
+                        "updated isKeyguardGoingAway"
+                    )
+                }
+            }
+
+        keyguardStateController.addCallback(callback)
+        // Adding the callback does not send an initial update.
+        trySendWithFailureLogging(
+            keyguardStateController.isKeyguardGoingAway,
+            TAG,
+            "initial isKeyguardGoingAway"
+        )
+
+        awaitClose { keyguardStateController.removeCallback(callback) }
+    }
+
     override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow {
         val callback =
             object : KeyguardStateController.Callback {
@@ -218,6 +253,25 @@
             }
             .distinctUntilChanged()
 
+    override val isDreaming: Flow<Boolean> =
+        conflatedCallbackFlow {
+                val callback =
+                    object : KeyguardUpdateMonitorCallback() {
+                        override fun onDreamingStateChanged(isDreaming: Boolean) {
+                            trySendWithFailureLogging(isDreaming, TAG, "updated isDreaming")
+                        }
+                    }
+                keyguardUpdateMonitor.registerCallback(callback)
+                trySendWithFailureLogging(
+                    keyguardUpdateMonitor.isDreaming,
+                    TAG,
+                    "initial isDreaming",
+                )
+
+                awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
+            }
+            .distinctUntilChanged()
+
     override val dozeAmount: Flow<Float> = conflatedCallbackFlow {
         val callback =
             object : StatusBarStateController.StateListener {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index e3d1a27..bce7d92 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -94,11 +94,13 @@
      */
     private val _transitions =
         MutableSharedFlow<TransitionStep>(
+            replay = 2,
             extraBufferCapacity = 10,
-            onBufferOverflow = BufferOverflow.DROP_OLDEST
+            onBufferOverflow = BufferOverflow.DROP_OLDEST,
         )
     override val transitions = _transitions.asSharedFlow().distinctUntilChanged()
     private var lastStep: TransitionStep = TransitionStep()
+    private var lastAnimator: ValueAnimator? = null
 
     /*
      * When manual control of the transition is requested, a unique [UUID] is used as the handle
@@ -106,19 +108,39 @@
      */
     private var updateTransitionId: UUID? = null
 
+    init {
+        // Seed with transitions signaling a boot into lockscreen state
+        emitTransition(
+            TransitionStep(
+                KeyguardState.OFF,
+                KeyguardState.LOCKSCREEN,
+                0f,
+                TransitionState.STARTED,
+            )
+        )
+        emitTransition(
+            TransitionStep(
+                KeyguardState.OFF,
+                KeyguardState.LOCKSCREEN,
+                1f,
+                TransitionState.FINISHED,
+            )
+        )
+    }
+
     override fun startTransition(info: TransitionInfo): UUID? {
         if (lastStep.transitionState != TransitionState.FINISHED) {
-            // Open questions:
-            // * Queue of transitions? buffer of 1?
-            // * Are transitions cancellable if a new one is triggered?
-            // * What validation does this need to do?
-            Log.wtf(TAG, "Transition still active: $lastStep")
-            return null
+            Log.i(TAG, "Transition still active: $lastStep, canceling")
         }
 
+        val startingValue = 1f - lastStep.value
+        lastAnimator?.cancel()
+        lastAnimator = info.animator
+
         info.animator?.let { animator ->
             // An animator was provided, so use it to run the transition
-            animator.setFloatValues(0f, 1f)
+            animator.setFloatValues(startingValue, 1f)
+            animator.duration = ((1f - startingValue) * animator.duration).toLong()
             val updateListener =
                 object : AnimatorUpdateListener {
                     override fun onAnimationUpdate(animation: ValueAnimator) {
@@ -134,15 +156,24 @@
             val adapter =
                 object : AnimatorListenerAdapter() {
                     override fun onAnimationStart(animation: Animator) {
-                        emitTransition(TransitionStep(info, 0f, TransitionState.STARTED))
+                        emitTransition(TransitionStep(info, startingValue, TransitionState.STARTED))
                     }
                     override fun onAnimationCancel(animation: Animator) {
-                        Log.i(TAG, "Cancelling transition: $info")
+                        endAnimation(animation, lastStep.value, TransitionState.CANCELED)
                     }
                     override fun onAnimationEnd(animation: Animator) {
-                        emitTransition(TransitionStep(info, 1f, TransitionState.FINISHED))
+                        endAnimation(animation, 1f, TransitionState.FINISHED)
+                    }
+
+                    private fun endAnimation(
+                        animation: Animator,
+                        value: Float,
+                        state: TransitionState
+                    ) {
+                        emitTransition(TransitionStep(info, value, state))
                         animator.removeListener(this)
                         animator.removeUpdateListener(updateListener)
+                        lastAnimator = null
                     }
                 }
             animator.addListener(adapter)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
index 0aeff7f..e5521c7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
@@ -20,10 +20,11 @@
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isSleepingOrStartingToSleep
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -35,18 +36,30 @@
 @Inject
 constructor(
     @Application private val scope: CoroutineScope,
-    private val keyguardRepository: KeyguardRepository,
+    private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionRepository: KeyguardTransitionRepository,
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) : TransitionInteractor("AOD<->LOCKSCREEN") {
 
     override fun start() {
         scope.launch {
-            keyguardRepository.isDozing
-                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+            /*
+             * Listening to the startedKeyguardTransitionStep (last started step) allows this code
+             * to interrupt an active transition, as long as they were either going to LOCKSCREEN or
+             * AOD state. One example is when the user presses the power button in the middle of an
+             * active transition.
+             */
+            keyguardInteractor.wakefulnessState
+                .sample(
+                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
+                    { a, b -> Pair(a, b) }
+                )
                 .collect { pair ->
-                    val (isDozing, keyguardState) = pair
-                    if (isDozing && keyguardState == KeyguardState.LOCKSCREEN) {
+                    val (wakefulnessState, lastStartedStep) = pair
+                    if (
+                        isSleepingOrStartingToSleep(wakefulnessState) &&
+                            lastStartedStep.to == KeyguardState.LOCKSCREEN
+                    ) {
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 name,
@@ -55,7 +68,10 @@
                                 getAnimator(),
                             )
                         )
-                    } else if (!isDozing && keyguardState == KeyguardState.AOD) {
+                    } else if (
+                        isWakingOrStartingToWake(wakefulnessState) &&
+                            lastStartedStep.to == KeyguardState.AOD
+                    ) {
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 name,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BouncerToGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BouncerToGoneTransitionInteractor.kt
new file mode 100644
index 0000000..dd29673
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BouncerToGoneTransitionInteractor.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.util.kotlin.sample
+import java.util.UUID
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class BouncerToGoneTransitionInteractor
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    private val keyguardInteractor: KeyguardInteractor,
+    private val shadeRepository: ShadeRepository,
+    private val keyguardTransitionRepository: KeyguardTransitionRepository,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor
+) : TransitionInteractor("BOUNCER->GONE") {
+
+    private var transitionId: UUID? = null
+
+    override fun start() {
+        listenForKeyguardGoingAway()
+    }
+
+    private fun listenForKeyguardGoingAway() {
+        scope.launch {
+            keyguardInteractor.isKeyguardGoingAway
+                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+                .collect { pair ->
+                    val (isKeyguardGoingAway, keyguardState) = pair
+                    if (isKeyguardGoingAway && keyguardState == KeyguardState.BOUNCER) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                ownerName = name,
+                                from = KeyguardState.BOUNCER,
+                                to = KeyguardState.GONE,
+                                animator = getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun getAnimator(): ValueAnimator {
+        return ValueAnimator().apply {
+            setInterpolator(Interpolators.LINEAR)
+            setDuration(TRANSITION_DURATION_MS)
+        }
+    }
+
+    companion object {
+        private const val TRANSITION_DURATION_MS = 300L
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt
new file mode 100644
index 0000000..c44cda4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class DreamingLockscreenTransitionInteractor
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardTransitionRepository: KeyguardTransitionRepository,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : TransitionInteractor("DREAMING<->LOCKSCREEN") {
+
+    override fun start() {
+        scope.launch {
+            keyguardInteractor.isDreaming
+                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+                .collect { pair ->
+                    val (isDreaming, keyguardState) = pair
+                    if (isDreaming && keyguardState == KeyguardState.LOCKSCREEN) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.LOCKSCREEN,
+                                KeyguardState.DREAMING,
+                                getAnimator(),
+                            )
+                        )
+                    } else if (!isDreaming && keyguardState == KeyguardState.DREAMING) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.DREAMING,
+                                KeyguardState.LOCKSCREEN,
+                                getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun getAnimator(): ValueAnimator {
+        return ValueAnimator().apply {
+            setInterpolator(Interpolators.LINEAR)
+            setDuration(TRANSITION_DURATION_MS)
+        }
+    }
+
+    companion object {
+        private const val TRANSITION_DURATION_MS = 500L
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt
new file mode 100644
index 0000000..9e2b724
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isSleepingOrStartingToSleep
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class DreamingToAodTransitionInteractor
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardTransitionRepository: KeyguardTransitionRepository,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : TransitionInteractor("DREAMING->AOD") {
+
+    override fun start() {
+        scope.launch {
+            keyguardInteractor.wakefulnessState
+                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+                .collect { pair ->
+                    val (wakefulnessState, keyguardState) = pair
+                    if (
+                        isSleepingOrStartingToSleep(wakefulnessState) &&
+                            keyguardState == KeyguardState.DREAMING
+                    ) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.DREAMING,
+                                KeyguardState.AOD,
+                                getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun getAnimator(): ValueAnimator {
+        return ValueAnimator().apply {
+            setInterpolator(Interpolators.LINEAR)
+            setDuration(TRANSITION_DURATION_MS)
+        }
+    }
+
+    companion object {
+        private const val TRANSITION_DURATION_MS = 300L
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 614ff8d..5a1c702 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -41,8 +41,15 @@
     val dozeAmount: Flow<Float> = repository.dozeAmount
     /** Whether the system is in doze mode. */
     val isDozing: Flow<Boolean> = repository.isDozing
+    /**
+     * Whether the system is dreaming. [isDreaming] will be always be true when [isDozing] is true,
+     * but not vice-versa.
+     */
+    val isDreaming: Flow<Boolean> = repository.isDreaming
     /** Whether the keyguard is showing or not. */
     val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
+    /** Whether the keyguard is going away. */
+    val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
     /** Whether the bouncer is showing or not. */
     val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
     /** The device wake/sleep state */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 92caa89..45eb6f5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -28,11 +28,13 @@
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
 import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceRegistry
+import com.android.systemui.keyguard.shared.model.KeyguardPickerFlag
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import dagger.Lazy
@@ -117,7 +119,7 @@
      *
      * @return `true` if the affordance was selected successfully; `false` otherwise.
      */
-    suspend fun select(slotId: String, affordanceId: String): Boolean {
+    fun select(slotId: String, affordanceId: String): Boolean {
         check(isUsingRepository)
 
         val slots = repository.get().getSlotPickerRepresentations()
@@ -152,7 +154,7 @@
      * @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
      * the affordance was not on the slot to begin with).
      */
-    suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
+    fun unselect(slotId: String, affordanceId: String?): Boolean {
         check(isUsingRepository)
 
         val slots = repository.get().getSlotPickerRepresentations()
@@ -187,7 +189,7 @@
     }
 
     /** Returns affordance IDs indexed by slot ID, for all known slots. */
-    suspend fun getSelections(): Map<String, List<String>> {
+    fun getSelections(): Map<String, List<String>> {
         check(isUsingRepository)
 
         val selections = repository.get().getSelections()
@@ -314,6 +316,15 @@
         return repository.get().getSlotPickerRepresentations()
     }
 
+    fun getPickerFlags(): List<KeyguardPickerFlag> {
+        return listOf(
+            KeyguardPickerFlag(
+                name = KeyguardQuickAffordanceProviderContract.FlagsTable.FLAG_NAME_FEATURE_ENABLED,
+                value = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES),
+            )
+        )
+    }
+
     companion object {
         private const val TAG = "KeyguardQuickAffordanceInteractor"
         private const val DELIMITER = "::"
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 57fb4a1..58a8093 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
@@ -41,12 +41,24 @@
         }
 
         scope.launch {
+            keyguardInteractor.isBouncerShowing.collect { logger.v("Bouncer showing", it) }
+        }
+
+        scope.launch { keyguardInteractor.isDozing.collect { logger.v("isDozing", it) } }
+
+        scope.launch {
             interactor.finishedKeyguardTransitionStep.collect {
                 logger.i("Finished transition", it)
             }
         }
 
         scope.launch {
+            interactor.canceledKeyguardTransitionStep.collect {
+                logger.i("Canceled transition", it)
+            }
+        }
+
+        scope.launch {
             interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index a7c6d44..43dd358e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -42,6 +42,9 @@
                     is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it")
                     is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
                     is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
+                    is BouncerToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
+                    is DreamingLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
+                    is DreamingToAodTransitionInteractor -> Log.d(TAG, "Started $it")
                 }
             it.start()
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 749183e..54a4f49 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -57,6 +57,14 @@
             lockscreenToAodTransition,
         )
 
+    /* The last [TransitionStep] with a [TransitionState] of STARTED */
+    val startedKeyguardTransitionStep: Flow<TransitionStep> =
+        repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
+
+    /* The last [TransitionStep] with a [TransitionState] of CANCELED */
+    val canceledKeyguardTransitionStep: Flow<TransitionStep> =
+        repository.transitions.filter { step -> step.transitionState == TransitionState.CANCELED }
+
     /* The last [TransitionStep] with a [TransitionState] of FINISHED */
     val finishedKeyguardTransitionStep: Flow<TransitionStep> =
         repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
@@ -64,8 +72,4 @@
     /* The last completed [KeyguardState] transition */
     val finishedKeyguardState: Flow<KeyguardState> =
         finishedKeyguardTransitionStep.map { step -> step.to }
-
-    /* The last [TransitionStep] with a [TransitionState] of STARTED */
-    val startedKeyguardTransitionStep: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
index fd4814d..cca2d56 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
@@ -56,10 +56,20 @@
     private fun listenForBouncerHiding() {
         scope.launch {
             keyguardInteractor.isBouncerShowing
-                .sample(keyguardInteractor.wakefulnessState, { a, b -> Pair(a, b) })
-                .collect { pair ->
-                    val (isBouncerShowing, wakefulnessState) = pair
-                    if (!isBouncerShowing) {
+                .sample(
+                    combine(
+                        keyguardInteractor.wakefulnessState,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
+                    ) { a, b ->
+                        Pair(a, b)
+                    },
+                    { a, bc -> Triple(a, bc.first, bc.second) }
+                )
+                .collect { triple ->
+                    val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple
+                    if (
+                        !isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER
+                    ) {
                         val to =
                             if (
                                 wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP ||
@@ -90,10 +100,10 @@
                     combine(
                         keyguardTransitionInteractor.finishedKeyguardState,
                         keyguardInteractor.statusBarState,
-                    ) { keyguardState, statusBarState ->
-                        Pair(keyguardState, statusBarState)
+                    ) { a, b ->
+                        Pair(a, b)
                     },
-                    { shadeModel, pair -> Triple(shadeModel, pair.first, pair.second) }
+                    { a, bc -> Triple(a, bc.first, bc.second) }
                 )
                 .collect { triple ->
                     val (shadeModel, keyguardState, statusBarState) = triple
@@ -116,8 +126,7 @@
                         )
                     } else {
                         // TODO (b/251849525): Remove statusbarstate check when that state is
-                        // integrated
-                        // into KeyguardTransitionRepository
+                        // integrated into KeyguardTransitionRepository
                         if (
                             keyguardState == KeyguardState.LOCKSCREEN &&
                                 shadeModel.isUserDragging &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
index 6c1adbd..4100f7a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.collect
@@ -34,23 +35,27 @@
 constructor(
     @Application private val scope: CoroutineScope,
     private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val keyguardTransitionRepository: KeyguardTransitionRepository,
 ) : TransitionInteractor("LOCKSCREEN->GONE") {
 
     override fun start() {
         scope.launch {
-            keyguardInteractor.isKeyguardShowing.collect { isShowing ->
-                if (!isShowing) {
-                    keyguardTransitionRepository.startTransition(
-                        TransitionInfo(
-                            name,
-                            KeyguardState.LOCKSCREEN,
-                            KeyguardState.GONE,
-                            getAnimator(),
+            keyguardInteractor.isKeyguardGoingAway
+                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+                .collect { pair ->
+                    val (isKeyguardGoingAway, keyguardState) = pair
+                    if (!isKeyguardGoingAway && keyguardState == KeyguardState.LOCKSCREEN) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.LOCKSCREEN,
+                                KeyguardState.GONE,
+                                getAnimator(),
+                            )
                         )
-                    )
+                    }
                 }
-            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index c22f4e7a..910cdf2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -117,7 +117,6 @@
     @JvmOverloads
     fun show(isScrimmed: Boolean) {
         // Reset some states as we show the bouncer.
-        repository.setShowMessage(null)
         repository.setOnScreenTurnedOff(false)
         repository.setKeyguardAuthenticated(null)
         repository.setPrimaryHide(false)
@@ -210,9 +209,12 @@
             expansion == KeyguardBouncer.EXPANSION_HIDDEN &&
                 oldExpansion != KeyguardBouncer.EXPANSION_HIDDEN
         ) {
-            repository.setPrimaryVisible(false)
-            repository.setPrimaryShow(null)
-            falsingCollector.onBouncerHidden()
+            /*
+             * There are cases where #hide() was not invoked, such as when
+             * NotificationPanelViewController controls the hide animation. Make sure the state gets
+             * updated by calling #hide() directly.
+             */
+            hide()
             DejankUtils.postAfterTraversal { primaryBouncerCallbackInteractor.dispatchReset() }
             primaryBouncerCallbackInteractor.dispatchFullyHidden()
         } else if (
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
index 37f33af..dbffeab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
@@ -46,5 +46,19 @@
 
     @Binds
     @IntoSet
+    abstract fun bouncerGone(impl: BouncerToGoneTransitionInteractor): TransitionInteractor
+
+    @Binds
+    @IntoSet
     abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor
+
+    @Binds
+    @IntoSet
+    abstract fun dreamingLockscreen(
+        impl: DreamingLockscreenTransitionInteractor
+    ): TransitionInteractor
+
+    @Binds
+    @IntoSet
+    abstract fun dreamingToAod(impl: DreamingToAodTransitionInteractor): TransitionInteractor
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardPickerFlag.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardPickerFlag.kt
new file mode 100644
index 0000000..a7a5957
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardPickerFlag.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.shared.model
+
+/** Represents a flag that's consumed by the settings or wallpaper picker app. */
+data class KeyguardPickerFlag(
+    val name: String,
+    val value: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
index 7958033..dd908c4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -17,12 +17,29 @@
 
 /** List of all possible states to transition to/from */
 enum class KeyguardState {
-    /**
-     * For initialization as well as when the security method is set to NONE, indicating that
-     * the keyguard should never be shown.
+    /*
+     * The display is completely off, as well as any sensors that would trigger the device to wake
+     * up.
      */
-    NONE,
-    /* Always-on Display. The device is in a low-power mode with a minimal UI visible */
+    OFF,
+    /**
+     * The device has entered a special low-power mode within SystemUI. Doze is technically a
+     * special dream service implementation. No UI is visible. In this state, a least some
+     * low-powered sensors such as lift to wake or tap to wake are enabled, or wake screen for
+     * notifications is enabled, allowing the device to quickly wake up.
+     */
+    DOZING,
+    /*
+     * A device state after the device times out, which can be from both LOCKSCREEN or GONE states.
+     * DOZING is an example of special version of this state. Dreams may be implemented by third
+     * parties to present their own UI over keyguard, like a screensaver.
+     */
+    DREAMING,
+    /**
+     * The device has entered a special low-power mode within SystemUI, also called the Always-on
+     * Display (AOD). A minimal UI is presented to show critical information. If the device is in
+     * low-power mode without a UI, then it is DOZING.
+     */
     AOD,
     /*
      * The security screen prompt UI, containing PIN, Password, Pattern, and all FPS
@@ -34,7 +51,6 @@
      * unlocked if SWIPE security method is used, or if face lockscreen bypass is false.
      */
     LOCKSCREEN,
-
     /*
      * Keyguard is no longer visible. In most cases the user has just authenticated and keyguard
      * is being removed, but there are other cases where the user is swiping away keyguard, such as
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
index 0e0465b..38a93b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionState.kt
@@ -17,7 +17,12 @@
 
 /** Possible states for a running transition between [State] */
 enum class TransitionState {
+    /* Transition has begun. */
     STARTED,
+    /* Transition is actively running. */
     RUNNING,
-    FINISHED
+    /* Transition has completed successfully. */
+    FINISHED,
+    /* Transition has been interrupted, and not completed successfully. */
+    CANCELED,
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt
index 732a6f7..767fd58 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionStep.kt
@@ -17,8 +17,8 @@
 
 /** This information will flow from the [KeyguardTransitionRepository] to control the UI layer */
 data class TransitionStep(
-    val from: KeyguardState = KeyguardState.NONE,
-    val to: KeyguardState = KeyguardState.NONE,
+    val from: KeyguardState = KeyguardState.OFF,
+    val to: KeyguardState = KeyguardState.OFF,
     val value: Float = 0f, // constrained [0.0, 1.0]
     val transitionState: TransitionState = TransitionState.FINISHED,
     val ownerName: String = "",
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
index 64f834d..92040f4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
@@ -24,5 +24,15 @@
     /** Device is now fully awake and interactive. */
     AWAKE,
     /** Signal that the device is now going to sleep. */
-    STARTING_TO_SLEEP,
+    STARTING_TO_SLEEP;
+
+    companion object {
+        fun isSleepingOrStartingToSleep(model: WakefulnessModel): Boolean {
+            return model == ASLEEP || model == STARTING_TO_SLEEP
+        }
+
+        fun isWakingOrStartingToWake(model: WakefulnessModel): Boolean {
+            return model == AWAKE || model == STARTING_TO_WAKE
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index a22958b..7739a45 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -94,6 +94,10 @@
                     viewModel.setBouncerViewDelegate(delegate)
                     launch {
                         viewModel.show.collect {
+                            hostViewController.showPromptReason(it.promptReason)
+                            it.errorMessage?.let { errorMessage ->
+                                hostViewController.showErrorMessage(errorMessage)
+                            }
                             hostViewController.showPrimarySecurityScreen()
                             hostViewController.appear(
                                 SystemBarUtils.getStatusBarHeight(view.context)
@@ -102,18 +106,6 @@
                     }
 
                     launch {
-                        viewModel.showPromptReason.collect { prompt ->
-                            hostViewController.showPromptReason(prompt)
-                        }
-                    }
-
-                    launch {
-                        viewModel.showBouncerErrorMessage.collect { errorMessage ->
-                            hostViewController.showErrorMessage(errorMessage)
-                        }
-                    }
-
-                    launch {
                         viewModel.showWithFullExpansion.collect { model ->
                             hostViewController.resetSecurityContainer()
                             hostViewController.showPromptReason(model.promptReason)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index 0781600..526ae74 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -26,7 +26,6 @@
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.map
 
 /** Models UI state for the lock screen bouncer; handles user input. */
@@ -45,13 +44,6 @@
     /** Observe whether bouncer is showing. */
     val show: Flow<KeyguardBouncerModel> = interactor.show
 
-    /** Observe bouncer prompt when bouncer is showing. */
-    val showPromptReason: Flow<Int> = interactor.show.map { it.promptReason }
-
-    /** Observe bouncer error message when bouncer is showing. */
-    val showBouncerErrorMessage: Flow<CharSequence> =
-        interactor.show.map { it.errorMessage }.filterNotNull()
-
     /** Observe visible expansion when bouncer is showing. */
     val showWithFullExpansion: Flow<KeyguardBouncerModel> =
         interactor.show.filter { it.expansionAmount == EXPANSION_VISIBLE }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
index a7f1b95..a8f39fa9a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
@@ -26,7 +26,8 @@
 import androidx.constraintlayout.widget.Barrier
 import com.android.systemui.R
 import com.android.systemui.media.controls.models.GutsViewHolder
-import com.android.systemui.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
 import com.android.systemui.util.animation.TransitionLayout
 
 private const val TAG = "MediaViewHolder"
@@ -38,6 +39,8 @@
     // Player information
     val albumView = itemView.requireViewById<ImageView>(R.id.album_art)
     val multiRippleView = itemView.requireViewById<MultiRippleView>(R.id.touch_ripple_view)
+    val turbulenceNoiseView =
+        itemView.requireViewById<TurbulenceNoiseView>(R.id.turbulence_noise_view)
     val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
     val titleText = itemView.requireViewById<TextView>(R.id.header_title)
     val artistText = itemView.requireViewById<TextView>(R.id.header_artist)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 45b319b..cf71d67 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -20,13 +20,12 @@
 import android.os.SystemProperties
 import android.util.Log
 import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.broadcast.BroadcastSender
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.util.MediaUiEventLogger
-import com.android.systemui.settings.CurrentUserTracker
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.util.time.SystemClock
 import java.util.SortedMap
@@ -62,14 +61,13 @@
 @Inject
 constructor(
     private val context: Context,
-    private val broadcastDispatcher: BroadcastDispatcher,
+    private val userTracker: UserTracker,
     private val broadcastSender: BroadcastSender,
     private val lockscreenUserManager: NotificationLockscreenUserManager,
     @Main private val executor: Executor,
     private val systemClock: SystemClock,
     private val logger: MediaUiEventLogger
 ) : MediaDataManager.Listener {
-    private val userTracker: CurrentUserTracker
     private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
     internal val listeners: Set<MediaDataManager.Listener>
         get() = _listeners.toSet()
@@ -81,15 +79,15 @@
     private var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA
     private var reactivatedKey: String? = null
 
-    init {
-        userTracker =
-            object : CurrentUserTracker(broadcastDispatcher) {
-                override fun onUserSwitched(newUserId: Int) {
-                    // Post this so we can be sure lockscreenUserManager already got the broadcast
-                    executor.execute { handleUserSwitched(newUserId) }
-                }
+    private val userTrackerCallback =
+        object : UserTracker.Callback {
+            override fun onUserChanged(newUser: Int, userContext: Context) {
+                handleUserSwitched(newUser)
             }
-        userTracker.startTracking()
+        }
+
+    init {
+        userTracker.addCallback(userTrackerCallback, executor)
     }
 
     override fun onMediaDataLoaded(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index 14dd990..3012bb4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -82,7 +82,6 @@
 import java.io.IOException
 import java.io.PrintWriter
 import java.util.concurrent.Executor
-import java.util.concurrent.Executors
 import javax.inject.Inject
 
 // URI fields to try loading album art from
@@ -154,6 +153,7 @@
 class MediaDataManager(
     private val context: Context,
     @Background private val backgroundExecutor: Executor,
+    @Main private val uiExecutor: Executor,
     @Main private val foregroundExecutor: DelayableExecutor,
     private val mediaControllerFactory: MediaControllerFactory,
     private val broadcastDispatcher: BroadcastDispatcher,
@@ -171,7 +171,8 @@
     private val systemClock: SystemClock,
     private val tunerService: TunerService,
     private val mediaFlags: MediaFlags,
-    private val logger: MediaUiEventLogger
+    private val logger: MediaUiEventLogger,
+    private val smartspaceManager: SmartspaceManager,
 ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
 
     companion object {
@@ -218,6 +219,7 @@
     constructor(
         context: Context,
         @Background backgroundExecutor: Executor,
+        @Main uiExecutor: Executor,
         @Main foregroundExecutor: DelayableExecutor,
         mediaControllerFactory: MediaControllerFactory,
         dumpManager: DumpManager,
@@ -233,10 +235,12 @@
         clock: SystemClock,
         tunerService: TunerService,
         mediaFlags: MediaFlags,
-        logger: MediaUiEventLogger
+        logger: MediaUiEventLogger,
+        smartspaceManager: SmartspaceManager,
     ) : this(
         context,
         backgroundExecutor,
+        uiExecutor,
         foregroundExecutor,
         mediaControllerFactory,
         broadcastDispatcher,
@@ -254,7 +258,8 @@
         clock,
         tunerService,
         mediaFlags,
-        logger
+        logger,
+        smartspaceManager,
     )
 
     private val appChangeReceiver =
@@ -314,21 +319,18 @@
 
         // Register for Smartspace data updates.
         smartspaceMediaDataProvider.registerListener(this)
-        val smartspaceManager: SmartspaceManager =
-            context.getSystemService(SmartspaceManager::class.java)
         smartspaceSession =
             smartspaceManager.createSmartspaceSession(
                 SmartspaceConfig.Builder(context, SMARTSPACE_UI_SURFACE_LABEL).build()
             )
         smartspaceSession?.let {
             it.addOnTargetsAvailableListener(
-                // Use a new thread listening to Smartspace updates instead of using the existing
-                // backgroundExecutor. SmartspaceSession has scheduled routine updates which can be
-                // unpredictable on test simulators, using the backgroundExecutor makes it's hard to
-                // test the threads numbers.
-                // Switch to use backgroundExecutor when SmartspaceSession has a good way to be
-                // mocked.
-                Executors.newCachedThreadPool(),
+                // Use a main uiExecutor thread listening to Smartspace updates instead of using
+                // the existing background executor.
+                // SmartspaceSession has scheduled routine updates which can be unpredictable on
+                // test simulators, using the backgroundExecutor makes it's hard to test the threads
+                // numbers.
+                uiExecutor,
                 SmartspaceSession.OnTargetsAvailableListener { targets ->
                     smartspaceMediaDataProvider.onTargetsAvailable(targets)
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 918417f..93be6a7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -29,7 +29,8 @@
 import com.android.settingslib.Utils
 import com.android.systemui.media.controls.models.player.MediaViewHolder
 import com.android.systemui.monet.ColorScheme
-import com.android.systemui.ripple.MultiRippleController
+import com.android.systemui.surfaceeffects.ripple.MultiRippleController
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController
 
 /**
  * A [ColorTransition] is an object that updates the colors of views each time [updateColorScheme]
@@ -102,13 +103,21 @@
     private val context: Context,
     private val mediaViewHolder: MediaViewHolder,
     private val multiRippleController: MultiRippleController,
+    private val turbulenceNoiseController: TurbulenceNoiseController,
     animatingColorTransitionFactory: AnimatingColorTransitionFactory
 ) {
     constructor(
         context: Context,
         mediaViewHolder: MediaViewHolder,
         multiRippleController: MultiRippleController,
-    ) : this(context, mediaViewHolder, multiRippleController, ::AnimatingColorTransition)
+        turbulenceNoiseController: TurbulenceNoiseController
+    ) : this(
+        context,
+        mediaViewHolder,
+        multiRippleController,
+        turbulenceNoiseController,
+        ::AnimatingColorTransition
+    )
 
     val bgColor = context.getColor(com.android.systemui.R.color.material_dynamic_secondary95)
     val surfaceColor =
@@ -129,6 +138,7 @@
             mediaViewHolder.actionPlayPause.backgroundTintList = accentColorList
             mediaViewHolder.gutsViewHolder.setAccentPrimaryColor(accentPrimary)
             multiRippleController.updateColor(accentPrimary)
+            turbulenceNoiseController.updateNoiseColor(accentPrimary)
         }
 
     val accentSecondary =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 215fa03..21e64e2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -31,6 +31,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
+import android.graphics.BlendMode;
 import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
@@ -64,6 +65,7 @@
 import androidx.constraintlayout.widget.ConstraintSet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.InstanceId;
 import com.android.settingslib.widget.AdaptiveIcon;
@@ -97,13 +99,16 @@
 import com.android.systemui.monet.Style;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.ripple.MultiRippleController;
-import com.android.systemui.ripple.RippleAnimation;
-import com.android.systemui.ripple.RippleAnimationConfig;
-import com.android.systemui.ripple.RippleShader;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.surfaceeffects.ripple.MultiRippleController;
+import com.android.systemui.surfaceeffects.ripple.MultiRippleView;
+import com.android.systemui.surfaceeffects.ripple.RippleAnimation;
+import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
+import com.android.systemui.surfaceeffects.ripple.RippleShader;
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig;
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController;
 import com.android.systemui.util.ColorUtilKt;
 import com.android.systemui.util.animation.TransitionLayout;
 import com.android.systemui.util.time.SystemClock;
@@ -216,7 +221,9 @@
     private boolean mShowBroadcastDialogButton = false;
     private String mSwitchBroadcastApp;
     private MultiRippleController mMultiRippleController;
+    private TurbulenceNoiseController mTurbulenceNoiseController;
     private FeatureFlags mFeatureFlags;
+    private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig = null;
 
     /**
      * Initialize a new control panel
@@ -394,9 +401,20 @@
         AnimatorSet exit = loadAnimator(R.anim.media_metadata_exit,
                 Interpolators.EMPHASIZED_ACCELERATE, titleText, artistText);
 
-        mMultiRippleController = new MultiRippleController(vh.getMultiRippleView());
+        MultiRippleView multiRippleView = vh.getMultiRippleView();
+        mMultiRippleController = new MultiRippleController(multiRippleView);
+        mTurbulenceNoiseController = new TurbulenceNoiseController(vh.getTurbulenceNoiseView());
+        multiRippleView.addRipplesFinishedListener(
+                () -> {
+                    if (mTurbulenceNoiseAnimationConfig == null) {
+                        mTurbulenceNoiseAnimationConfig = createLingeringNoiseAnimation();
+                    }
+                    // Color will be correctly updated in ColorSchemeTransition.
+                    mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
+                }
+        );
         mColorSchemeTransition = new ColorSchemeTransition(
-                mContext, mMediaViewHolder, mMultiRippleController);
+                mContext, mMediaViewHolder, mMultiRippleController, mTurbulenceNoiseController);
         mMetadataAnimationHandler = new MetadataAnimationHandler(exit, enter);
     }
 
@@ -571,7 +589,10 @@
         seamlessView.setContentDescription(deviceString);
         seamlessView.setOnClickListener(
                 v -> {
-                    if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    if (mFalsingManager.isFalseTap(
+                            mFeatureFlags.isEnabled(Flags.MEDIA_FALSING_PENALTY)
+                                    ? FalsingManager.MODERATE_PENALTY :
+                                    FalsingManager.LOW_PENALTY)) {
                         return;
                     }
 
@@ -994,7 +1015,10 @@
             } else {
                 button.setEnabled(true);
                 button.setOnClickListener(v -> {
-                    if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    if (!mFalsingManager.isFalseTap(
+                            mFeatureFlags.isEnabled(Flags.MEDIA_FALSING_PENALTY)
+                                    ? FalsingManager.MODERATE_PENALTY :
+                                    FalsingManager.LOW_PENALTY)) {
                         mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId);
                         logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT);
                         action.run();
@@ -1027,7 +1051,7 @@
                         /* maxWidth= */ maxSize,
                         /* maxHeight= */ maxSize,
                         /* pixelDensity= */ getContext().getResources().getDisplayMetrics().density,
-                        mColorSchemeTransition.getAccentPrimary().getTargetColor(),
+                        mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
                         /* opacity= */ 100,
                         /* shouldFillRipple= */ false,
                         /* sparkleStrength= */ 0f,
@@ -1036,6 +1060,26 @@
         );
     }
 
+    private TurbulenceNoiseAnimationConfig createLingeringNoiseAnimation() {
+        return new TurbulenceNoiseAnimationConfig(
+                TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_GRID_COUNT,
+                TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
+                /* noiseMoveSpeedX= */ 0f,
+                /* noiseMoveSpeedY= */ 0f,
+                TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
+                /* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
+                // We want to add (BlendMode.PLUS) the turbulence noise on top of the album art.
+                // Thus, set the background color with alpha 0.
+                /* backgroundColor= */ ColorUtils.setAlphaComponent(Color.BLACK, 0),
+                TurbulenceNoiseAnimationConfig.DEFAULT_OPACITY,
+                /* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
+                /* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
+                TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_DURATION_IN_MILLIS,
+                this.getContext().getResources().getDisplayMetrics().density,
+                BlendMode.PLUS,
+                /* onAnimationEnd= */ null
+        );
+    }
     private void clearButton(final ImageButton button) {
         button.setImageDrawable(null);
         button.setContentDescription(null);
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
index a4a96806..647beb9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
@@ -61,7 +61,7 @@
             @SuppressLint("WrongConstant") // sysui allowed to call STATUS_BAR_SERVICE
             val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)
                     as StatusBarManager
-            val routeInfo = MediaRoute2Info.Builder("id", args[0])
+            val routeInfo = MediaRoute2Info.Builder(if (args.size >= 4) args[3] else "id", args[0])
                     .addFeature("feature")
             val useAppIcon = !(args.size >= 3 && args[2] == "useAppIcon=false")
             if (useAppIcon) {
@@ -107,7 +107,7 @@
 
         override fun help(pw: PrintWriter) {
             pw.println("Usage: adb shell cmd statusbar $SENDER_COMMAND " +
-                    "<deviceName> <chipState> useAppIcon=[true|false]")
+                    "<deviceName> <chipState> useAppIcon=[true|false] <id>")
         }
     }
 
@@ -127,8 +127,10 @@
             @SuppressLint("WrongConstant") // sysui is allowed to call STATUS_BAR_SERVICE
             val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)
                     as StatusBarManager
-            val routeInfo = MediaRoute2Info.Builder("id", "Test Name")
-                .addFeature("feature")
+            val routeInfo = MediaRoute2Info.Builder(
+                if (args.size >= 3) args[2] else "id",
+                "Test Name"
+            ).addFeature("feature")
             val useAppIcon = !(args.size >= 2 && args[1] == "useAppIcon=false")
             if (useAppIcon) {
                 routeInfo.setClientPackageName(TEST_PACKAGE_NAME)
@@ -144,7 +146,7 @@
 
         override fun help(pw: PrintWriter) {
             pw.println("Usage: adb shell cmd statusbar $RECEIVER_COMMAND " +
-                    "<chipState> useAppIcon=[true|false]")
+                    "<chipState> useAppIcon=[true|false] <id>")
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 8bddffc..691953a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -121,18 +121,32 @@
         uiEventLogger.logReceiverStateChange(chipState)
 
         if (chipState == ChipStateReceiver.FAR_FROM_SENDER) {
-            removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER.name)
+            removeView(routeInfo.id, removalReason = ChipStateReceiver.FAR_FROM_SENDER.name)
             return
         }
         if (appIcon == null) {
-            displayView(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName))
+            displayView(
+                ChipReceiverInfo(
+                    routeInfo,
+                    appIconDrawableOverride = null,
+                    appName,
+                    id = routeInfo.id,
+                )
+            )
             return
         }
 
         appIcon.loadDrawableAsync(
                 context,
                 Icon.OnDrawableLoadedListener { drawable ->
-                    displayView(ChipReceiverInfo(routeInfo, drawable, appName))
+                    displayView(
+                        ChipReceiverInfo(
+                            routeInfo,
+                            drawable,
+                            appName,
+                            id = routeInfo.id,
+                        )
+                    )
                 },
                 // Notify the listener on the main handler since the listener will update
                 // the UI.
@@ -234,4 +248,5 @@
     val appNameOverride: CharSequence?,
     override val windowTitle: String = MediaTttUtils.WINDOW_TITLE_RECEIVER,
     override val wakeReason: String = MediaTttUtils.WAKE_REASON_RECEIVER,
+    override val id: String,
 ) : TemporaryViewInfo()
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
index e354a03..1ea2025 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
@@ -18,8 +18,8 @@
 
 import android.content.Context
 import android.util.AttributeSet
-import com.android.systemui.ripple.RippleShader
-import com.android.systemui.ripple.RippleView
+import com.android.systemui.surfaceeffects.ripple.RippleShader
+import com.android.systemui.surfaceeffects.ripple.RippleView
 
 /**
  * An expanding ripple effect for the media tap-to-transfer receiver chip.
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
index d1ea2d0..bb7bc6f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -108,7 +108,7 @@
             }
 
             displayedState = null
-            chipbarCoordinator.removeView(removalReason)
+            chipbarCoordinator.removeView(routeInfo.id, removalReason)
         } else {
             displayedState = chipState
             chipbarCoordinator.displayView(
@@ -162,6 +162,7 @@
             windowTitle = MediaTttUtils.WINDOW_TITLE_SENDER,
             wakeReason = MediaTttUtils.WAKE_REASON_SENDER,
             timeoutMs = chipStateSender.timeout,
+            id = routeInfo.id,
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index e8b49cd..7a77c47 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -16,19 +16,19 @@
 
 package com.android.systemui.mediaprojection.appselector.data
 
-import android.app.ActivityManager
 import android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.kotlin.getOrNull
 import com.android.wm.shell.recents.RecentTasks
 import com.android.wm.shell.util.GroupedRecentTaskInfo
 import java.util.Optional
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.withContext
-import java.util.concurrent.Executor
 
 interface RecentTaskListProvider {
     /** Loads recent tasks, the returned task list is from the most-recent to least-recent order */
@@ -40,7 +40,8 @@
 constructor(
     @Background private val coroutineDispatcher: CoroutineDispatcher,
     @Background private val backgroundExecutor: Executor,
-    private val recentTasks: Optional<RecentTasks>
+    private val recentTasks: Optional<RecentTasks>,
+    private val userTracker: UserTracker
 ) : RecentTaskListProvider {
 
     private val recents by lazy { recentTasks.getOrNull() }
@@ -67,10 +68,8 @@
             getRecentTasks(
                 Integer.MAX_VALUE,
                 RECENT_IGNORE_UNAVAILABLE,
-                ActivityManager.getCurrentUser(),
+                userTracker.userId,
                 backgroundExecutor
-            ) { tasks ->
-                continuation.resume(tasks)
-            }
+            ) { tasks -> continuation.resume(tasks) }
         }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
index b682bd1..d4991f9 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
@@ -148,6 +148,7 @@
 
         val currentRotation: Int = display.rotation
         val displayWidthPx = windowMetrics.bounds.width()
+        val displayHeightPx = windowMetrics.bounds.height()
         val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
         val isTablet = isTablet(context)
         val taskbarSize =
@@ -163,6 +164,7 @@
             measuredWidth,
             measuredHeight,
             displayWidthPx,
+            displayHeightPx,
             taskbarSize,
             isTablet,
             currentRotation,
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 c319a82..ed1e018 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -59,7 +59,6 @@
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
@@ -71,7 +70,7 @@
 import com.android.systemui.plugins.NavigationEdgeBackPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputChannelCompat;
@@ -102,8 +101,8 @@
 /**
  * Utility class to handle edge swipes for back gesture
  */
-public class EdgeBackGestureHandler extends CurrentUserTracker
-        implements PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> {
+public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBackPlugin>,
+        ProtoTraceable<SystemUiTraceProto> {
 
     private static final String TAG = "EdgeBackGestureHandler";
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -172,6 +171,7 @@
 
 
     private final Context mContext;
+    private final UserTracker mUserTracker;
     private final OverviewProxyService mOverviewProxyService;
     private final SysUiState mSysUiState;
     private Runnable mStateChangeCallback;
@@ -319,6 +319,15 @@
     private final Consumer<Boolean> mOnIsInPipStateChangedListener =
             (isInPip) -> mIsInPip = isInPip;
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    updateIsEnabled();
+                    updateCurrentUserResources();
+                }
+            };
+
     EdgeBackGestureHandler(
             Context context,
             OverviewProxyService overviewProxyService,
@@ -326,7 +335,7 @@
             PluginManager pluginManager,
             @Main Executor executor,
             @Background Executor backgroundExecutor,
-            BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
             ProtoTracer protoTracer,
             NavigationModeController navigationModeController,
             BackPanelController.Factory backPanelControllerFactory,
@@ -338,11 +347,11 @@
             Provider<NavigationBarEdgePanel> navigationBarEdgePanelProvider,
             Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider,
             FeatureFlags featureFlags) {
-        super(broadcastDispatcher);
         mContext = context;
         mDisplayId = context.getDisplayId();
         mMainExecutor = executor;
         mBackgroundExecutor = backgroundExecutor;
+        mUserTracker = userTracker;
         mOverviewProxyService = overviewProxyService;
         mSysUiState = sysUiState;
         mPluginManager = pluginManager;
@@ -444,12 +453,6 @@
         }
     }
 
-    @Override
-    public void onUserSwitched(int newUserId) {
-        updateIsEnabled();
-        updateCurrentUserResources();
-    }
-
     /**
      * @see NavigationBarView#onAttachedToWindow()
      */
@@ -459,7 +462,7 @@
         mOverviewProxyService.addCallback(mQuickSwitchListener);
         mSysUiState.addCallback(mSysUiStateCallback);
         updateIsEnabled();
-        startTracking();
+        mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
     }
 
     /**
@@ -471,7 +474,7 @@
         mOverviewProxyService.removeCallback(mQuickSwitchListener);
         mSysUiState.removeCallback(mSysUiStateCallback);
         updateIsEnabled();
-        stopTracking();
+        mUserTracker.removeCallback(mUserChangedCallback);
     }
 
     /**
@@ -1074,7 +1077,7 @@
         private final PluginManager mPluginManager;
         private final Executor mExecutor;
         private final Executor mBackgroundExecutor;
-        private final BroadcastDispatcher mBroadcastDispatcher;
+        private final UserTracker mUserTracker;
         private final ProtoTracer mProtoTracer;
         private final NavigationModeController mNavigationModeController;
         private final BackPanelController.Factory mBackPanelControllerFactory;
@@ -1094,7 +1097,7 @@
                        PluginManager pluginManager,
                        @Main Executor executor,
                        @Background Executor backgroundExecutor,
-                       BroadcastDispatcher broadcastDispatcher,
+                       UserTracker userTracker,
                        ProtoTracer protoTracer,
                        NavigationModeController navigationModeController,
                        BackPanelController.Factory backPanelControllerFactory,
@@ -1112,7 +1115,7 @@
             mPluginManager = pluginManager;
             mExecutor = executor;
             mBackgroundExecutor = backgroundExecutor;
-            mBroadcastDispatcher = broadcastDispatcher;
+            mUserTracker = userTracker;
             mProtoTracer = protoTracer;
             mNavigationModeController = navigationModeController;
             mBackPanelControllerFactory = backPanelControllerFactory;
@@ -1135,7 +1138,7 @@
                     mPluginManager,
                     mExecutor,
                     mBackgroundExecutor,
-                    mBroadcastDispatcher,
+                    mUserTracker,
                     mProtoTracer,
                     mNavigationModeController,
                     mBackPanelControllerFactory,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 0697133..f92bbf7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -364,13 +364,18 @@
     private void distributeTiles() {
         emptyAndInflateOrRemovePages();
 
-        final int tileCount = mPages.get(0).maxTiles();
-        if (DEBUG) Log.d(TAG, "Distributing tiles");
+        final int tilesPerPageCount = mPages.get(0).maxTiles();
         int index = 0;
-        final int NT = mTiles.size();
-        for (int i = 0; i < NT; i++) {
+        final int totalTilesCount = mTiles.size();
+        if (DEBUG) {
+            Log.d(TAG, "Distributing tiles: "
+                    + "[tilesPerPageCount=" + tilesPerPageCount + "]"
+                    + "[totalTilesCount=" + totalTilesCount + "]"
+            );
+        }
+        for (int i = 0; i < totalTilesCount; i++) {
             TileRecord tile = mTiles.get(i);
-            if (mPages.get(index).mRecords.size() == tileCount) index++;
+            if (mPages.get(index).mRecords.size() == tilesPerPageCount) index++;
             if (DEBUG) {
                 Log.d(TAG, "Adding " + tile.tile.getClass().getSimpleName() + " to "
                         + index);
@@ -577,8 +582,8 @@
         });
         setOffscreenPageLimit(lastPageNumber); // Ensure the page to reveal has been inflated.
         int dx = getWidth() * lastPageNumber;
-        mScroller.startScroll(getScrollX(), getScrollY(), isLayoutRtl() ? -dx  : dx, 0,
-            REVEAL_SCROLL_DURATION_MILLIS);
+        mScroller.startScroll(getScrollX(), getScrollY(), isLayoutRtl() ? -dx : dx, 0,
+                REVEAL_SCROLL_DURATION_MILLIS);
         postInvalidateOnAnimation();
     }
 
@@ -738,6 +743,7 @@
 
     public interface PageListener {
         int INVALID_PAGE = -1;
+
         void onPageChanged(boolean isFirst, int pageNumber);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 20f1a8e..1422a25 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -515,7 +515,13 @@
     public void setExpanded(boolean expanded) {
         if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
         mQsExpanded = expanded;
-        updateQsPanelControllerListening();
+        if (mInSplitShade && mQsExpanded) {
+            // in split shade QS is expanded immediately when shade expansion starts and then we
+            // also need to listen to changes - otherwise QS is updated only once its fully expanded
+            setListening(true);
+        } else {
+            updateQsPanelControllerListening();
+        }
         updateQsState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 2a80de0..dd88c83 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -25,6 +25,7 @@
 import android.content.res.Configuration;
 import android.content.res.Configuration.Orientation;
 import android.metrics.LogMaker;
+import android.util.Log;
 import android.view.View;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -38,6 +39,7 @@
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileViewImpl;
 import com.android.systemui.util.LargeScreenUtils;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.animation.DisappearParameters;
@@ -237,6 +239,16 @@
     private void addTile(final QSTile tile, boolean collapsedView) {
         final TileRecord r =
                 new TileRecord(tile, mHost.createTileView(getContext(), tile, collapsedView));
+        // TODO(b/250618218): Remove the QSLogger in QSTileViewImpl once we know the root cause of
+        // b/250618218.
+        try {
+            QSTileViewImpl qsTileView = (QSTileViewImpl) (r.tileView);
+            if (qsTileView != null) {
+                qsTileView.setQsLogger(mQSLogger);
+            }
+        } catch (ClassCastException e) {
+            Log.e(TAG, "Failed to cast QSTileView to QSTileViewImpl", e);
+        }
         mView.addTile(r);
         mRecords.add(r);
         mCachedSpecs = getTilesSpecs();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java
index 6b0abd4..7794fa0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.qs;
 
-import android.app.ActivityManager;
 import android.database.ContentObserver;
 import android.os.Handler;
 
@@ -47,10 +46,6 @@
         this(settingsProxy, handler, settingName, userId, 0);
     }
 
-    public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName) {
-        this(settingsProxy, handler, settingName, ActivityManager.getCurrentUser());
-    }
-
     public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName,
             int userId, int defaultValue) {
         super(handler);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 3d00dd4..7ee4047 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -123,7 +123,6 @@
     public boolean updateResources() {
         final Resources res = mContext.getResources();
         mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
-        updateColumns();
         mMaxCellHeight = mContext.getResources().getDimensionPixelSize(mCellHeightResId);
         mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
         mSidePadding = useSidePadding() ? mCellMarginHorizontal / 2 : 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index cf10c79..79fcc7d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -82,12 +82,12 @@
         DefaultItemAnimator animator = new DefaultItemAnimator();
         animator.setMoveDuration(TileAdapter.MOVE_DURATION);
         mRecyclerView.setItemAnimator(animator);
+
+        updateTransparentViewHeight();
     }
 
     void updateResources() {
-        LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
-        lp.height = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
-        mTransparentView.setLayoutParams(lp);
+        updateTransparentViewHeight();
         mRecyclerView.getAdapter().notifyItemChanged(0);
     }
 
@@ -236,4 +236,10 @@
     public boolean isOpening() {
         return mOpening;
     }
+
+    private void updateTransparentViewHeight() {
+        LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
+        lp.height = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
+        mTransparentView.setLayoutParams(lp);
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 931dc8d..9f6317f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -129,12 +129,36 @@
         })
     }
 
-    fun logInternetTileUpdate(lastType: Int, callback: String) {
+    fun logInternetTileUpdate(tileSpec: String, lastType: Int, callback: String) {
         log(VERBOSE, {
+            str1 = tileSpec
             int1 = lastType
-            str1 = callback
+            str2 = callback
         }, {
-            "mLastTileState=$int1, Callback=$str1."
+            "[$str1] mLastTileState=$int1, Callback=$str2."
+        })
+    }
+
+    // TODO(b/250618218): Remove this method once we know the root cause of b/250618218.
+    fun logTileBackgroundColorUpdateIfInternetTile(
+        tileSpec: String,
+        state: Int,
+        disabledByPolicy: Boolean,
+        color: Int
+    ) {
+        // This method is added to further debug b/250618218 which has only been observed from the
+        // InternetTile, so we are only logging the background color change for the InternetTile
+        // to avoid spamming the QSLogger.
+        if (tileSpec != "internet") {
+            return
+        }
+        log(VERBOSE, {
+            str1 = tileSpec
+            int1 = state
+            bool1 = disabledByPolicy
+            int2 = color
+        }, {
+            "[$str1] state=$int1, disabledByPolicy=$bool1, color=$int2."
         })
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 972b243..b355d4b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -50,6 +50,7 @@
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.plugins.qs.QSTile.BooleanState
 import com.android.systemui.plugins.qs.QSTileView
+import com.android.systemui.qs.logging.QSLogger
 import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH
 import java.util.Objects
 
@@ -116,7 +117,7 @@
     protected lateinit var sideView: ViewGroup
     private lateinit var customDrawableView: ImageView
     private lateinit var chevronView: ImageView
-
+    private var mQsLogger: QSLogger? = null
     protected var showRippleEffect = true
 
     private lateinit var ripple: RippleDrawable
@@ -188,6 +189,10 @@
         updateHeight()
     }
 
+    fun setQsLogger(qsLogger: QSLogger) {
+        mQsLogger = qsLogger
+    }
+
     fun updateResources() {
         FontSizeUtils.updateFontSize(label, R.dimen.qs_tile_text_size)
         FontSizeUtils.updateFontSize(secondaryLabel, R.dimen.qs_tile_text_size)
@@ -493,6 +498,11 @@
         // Colors
         if (state.state != lastState || state.disabledByPolicy || lastDisabledByPolicy) {
             singleAnimator.cancel()
+            mQsLogger?.logTileBackgroundColorUpdateIfInternetTile(
+                    state.spec,
+                    state.state,
+                    state.disabledByPolicy,
+                    getBackgroundColorForState(state.state, state.disabledByPolicy))
             if (allowAnimations) {
                 singleAnimator.setValues(
                         colorValuesHolder(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 86d4fa3..033dbe0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -48,6 +48,7 @@
 import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Inject;
@@ -74,14 +75,16 @@
             QSLogger qsLogger,
             BroadcastDispatcher broadcastDispatcher,
             Lazy<ConnectivityManager> lazyConnectivityManager,
-            GlobalSettings globalSettings
+            GlobalSettings globalSettings,
+            UserTracker userTracker
     ) {
         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
         mBroadcastDispatcher = broadcastDispatcher;
         mLazyConnectivityManager = lazyConnectivityManager;
 
-        mSetting = new SettingObserver(globalSettings, mHandler, Global.AIRPLANE_MODE_ON) {
+        mSetting = new SettingObserver(globalSettings, mHandler, Global.AIRPLANE_MODE_ON,
+                userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
                 // mHandler is the background handler so calling this is OK
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
index bebd580..5bc209a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
@@ -70,7 +70,7 @@
     private final SettingObserver mDreamSettingObserver;
     private final UserTracker mUserTracker;
     private final boolean mDreamSupported;
-    private final boolean mDreamOnlyEnabledForSystemUser;
+    private final boolean mDreamOnlyEnabledForDockUser;
 
     private boolean mIsDocked = false;
 
@@ -100,22 +100,22 @@
             BroadcastDispatcher broadcastDispatcher,
             UserTracker userTracker,
             @Named(DreamModule.DREAM_SUPPORTED) boolean dreamSupported,
-            @Named(DreamModule.DREAM_ONLY_ENABLED_FOR_SYSTEM_USER)
-                    boolean dreamOnlyEnabledForSystemUser
+            @Named(DreamModule.DREAM_ONLY_ENABLED_FOR_DOCK_USER)
+                    boolean dreamOnlyEnabledForDockUser
     ) {
         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
         mDreamManager = dreamManager;
         mBroadcastDispatcher = broadcastDispatcher;
         mEnabledSettingObserver = new SettingObserver(secureSettings, mHandler,
-                Settings.Secure.SCREENSAVER_ENABLED) {
+                Settings.Secure.SCREENSAVER_ENABLED, userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
                 refreshState();
             }
         };
         mDreamSettingObserver = new SettingObserver(secureSettings, mHandler,
-                Settings.Secure.SCREENSAVER_COMPONENTS) {
+                Settings.Secure.SCREENSAVER_COMPONENTS, userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
                 refreshState();
@@ -123,7 +123,7 @@
         };
         mUserTracker = userTracker;
         mDreamSupported = dreamSupported;
-        mDreamOnlyEnabledForSystemUser = dreamOnlyEnabledForSystemUser;
+        mDreamOnlyEnabledForDockUser = dreamOnlyEnabledForDockUser;
     }
 
     @Override
@@ -203,7 +203,8 @@
         // For now, restrict to debug users.
         return Build.isDebuggable()
                 && mDreamSupported
-                && (!mDreamOnlyEnabledForSystemUser || mUserTracker.getUserHandle().isSystem());
+                // TODO(b/257333623): Allow the Dock User to be non-SystemUser user in HSUM.
+                && (!mDreamOnlyEnabledForDockUser || mUserTracker.getUserHandle().isSystem());
     }
 
     @VisibleForTesting
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 d304024..5670b6d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -383,7 +383,8 @@
 
     @Override
     protected void handleUpdateState(SignalState state, Object arg) {
-        mQSLogger.logInternetTileUpdate(mLastTileState, arg == null ? "null" : arg.toString());
+        mQSLogger.logInternetTileUpdate(
+                getTileSpec(), mLastTileState, arg == null ? "null" : arg.toString());
         if (arg instanceof CellularCallbackInfo) {
             mLastTileState = 0;
             handleUpdateCellularState(state, arg);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 0dfb2f4..ee3b130 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -32,12 +32,14 @@
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
 import android.text.Html;
+import android.text.Layout;
 import android.text.TextUtils;
 import android.text.method.LinkMovementMethod;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewStub;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.Button;
@@ -61,6 +63,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -71,6 +74,8 @@
 import java.util.List;
 import java.util.concurrent.Executor;
 
+import javax.inject.Inject;
+
 /**
  * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks.
  */
@@ -85,6 +90,7 @@
 
     private final Handler mHandler;
     private final Executor mBackgroundExecutor;
+    private final DialogLaunchAnimator mDialogLaunchAnimator;
 
     @VisibleForTesting
     protected InternetAdapter mAdapter;
@@ -108,6 +114,7 @@
     private LinearLayout mInternetDialogLayout;
     private LinearLayout mConnectedWifListLayout;
     private LinearLayout mMobileNetworkLayout;
+    private LinearLayout mSecondaryMobileNetworkLayout;
     private LinearLayout mTurnWifiOnLayout;
     private LinearLayout mEthernetLayout;
     private TextView mWifiToggleTitleText;
@@ -122,6 +129,8 @@
     private ImageView mSignalIcon;
     private TextView mMobileTitleText;
     private TextView mMobileSummaryText;
+    private TextView mSecondaryMobileTitleText;
+    private TextView  mSecondaryMobileSummaryText;
     private TextView mAirplaneModeSummaryText;
     private Switch mMobileDataToggle;
     private View mMobileToggleDivider;
@@ -157,9 +166,11 @@
         mInternetDialogSubTitle.setText(getSubtitleText());
     };
 
+    @Inject
     public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
             InternetDialogController internetDialogController, boolean canConfigMobileData,
             boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
+            DialogLaunchAnimator dialogLaunchAnimator,
             @Main Handler handler, @Background Executor executor,
             KeyguardStateController keyguardStateController) {
         super(context);
@@ -182,6 +193,7 @@
         mKeyguard = keyguardStateController;
 
         mUiEventLogger = uiEventLogger;
+        mDialogLaunchAnimator = dialogLaunchAnimator;
         mAdapter = new InternetAdapter(mInternetDialogController);
         if (!aboveStatusBar) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
@@ -237,15 +249,7 @@
         mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
         mInternetDialogTitle.setText(getDialogTitleText());
         mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
-
-        TypedArray typedArray = mContext.obtainStyledAttributes(
-                new int[]{android.R.attr.selectableItemBackground});
-        try {
-            mBackgroundOff = typedArray.getDrawable(0 /* index */);
-        } finally {
-            typedArray.recycle();
-        }
-
+        mBackgroundOff = mContext.getDrawable(R.drawable.internet_dialog_selected_effect);
         setOnClickListener();
         mTurnWifiOnLayout.setBackground(null);
         mAirplaneModeButton.setVisibility(
@@ -286,6 +290,9 @@
         mMobileNetworkLayout.setOnClickListener(null);
         mMobileDataToggle.setOnCheckedChangeListener(null);
         mConnectedWifListLayout.setOnClickListener(null);
+        if (mSecondaryMobileNetworkLayout != null) {
+            mSecondaryMobileNetworkLayout.setOnClickListener(null);
+        }
         mSeeAllLayout.setOnClickListener(null);
         mWiFiToggle.setOnCheckedChangeListener(null);
         mDoneButton.setOnClickListener(null);
@@ -340,6 +347,10 @@
 
     private void setOnClickListener() {
         mMobileNetworkLayout.setOnClickListener(v -> {
+            int autoSwitchNonDdsSubId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+            if (autoSwitchNonDdsSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                showTurnOffAutoDataSwitchDialog(autoSwitchNonDdsSubId);
+            }
             if (mInternetDialogController.isMobileDataEnabled()
                     && !mInternetDialogController.isDeviceLocked()) {
                 if (!mInternetDialogController.activeNetworkIsCellular()) {
@@ -389,41 +400,28 @@
         if (!mInternetDialogController.hasActiveSubId()
                 && (!isWifiEnabled || !isCarrierNetworkActive)) {
             mMobileNetworkLayout.setVisibility(View.GONE);
+            if (mSecondaryMobileNetworkLayout != null) {
+                mSecondaryMobileNetworkLayout.setVisibility(View.GONE);
+            }
         } else {
             mMobileNetworkLayout.setVisibility(View.VISIBLE);
             mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled());
-            mMobileTitleText.setText(getMobileNetworkTitle());
-            String summary = getMobileNetworkSummary();
+            mMobileTitleText.setText(getMobileNetworkTitle(mDefaultDataSubId));
+            String summary = getMobileNetworkSummary(mDefaultDataSubId);
             if (!TextUtils.isEmpty(summary)) {
                 mMobileSummaryText.setText(
                         Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY));
+                mMobileSummaryText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
                 mMobileSummaryText.setVisibility(View.VISIBLE);
             } else {
                 mMobileSummaryText.setVisibility(View.GONE);
             }
             mBackgroundExecutor.execute(() -> {
-                Drawable drawable = getSignalStrengthDrawable();
+                Drawable drawable = getSignalStrengthDrawable(mDefaultDataSubId);
                 mHandler.post(() -> {
                     mSignalIcon.setImageDrawable(drawable);
                 });
             });
-            mMobileTitleText.setTextAppearance(isNetworkConnected
-                    ? R.style.TextAppearance_InternetDialog_Active
-                    : R.style.TextAppearance_InternetDialog);
-            int secondaryRes = isNetworkConnected
-                    ? R.style.TextAppearance_InternetDialog_Secondary_Active
-                    : R.style.TextAppearance_InternetDialog_Secondary;
-            mMobileSummaryText.setTextAppearance(secondaryRes);
-            // Set airplane mode to the summary for carrier network
-            if (mInternetDialogController.isAirplaneModeEnabled()) {
-                mAirplaneModeSummaryText.setVisibility(View.VISIBLE);
-                mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode));
-                mAirplaneModeSummaryText.setTextAppearance(secondaryRes);
-            } else {
-                mAirplaneModeSummaryText.setVisibility(View.GONE);
-            }
-            mMobileNetworkLayout.setBackground(
-                    isNetworkConnected ? mBackgroundOn : mBackgroundOff);
 
             TypedArray array = mContext.obtainStyledAttributes(
                     R.style.InternetDialog_Divider_Active, new int[]{android.R.attr.background});
@@ -436,6 +434,86 @@
             mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
             mMobileToggleDivider.setVisibility(
                     mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
+
+            // Display the info for the non-DDS if it's actively being used
+            int autoSwitchNonDdsSubId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+            int nonDdsVisibility = autoSwitchNonDdsSubId
+                    != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? View.VISIBLE : View.GONE;
+
+            int secondaryRes = isNetworkConnected
+                    ? R.style.TextAppearance_InternetDialog_Secondary_Active
+                    : R.style.TextAppearance_InternetDialog_Secondary;
+            if (nonDdsVisibility == View.VISIBLE) {
+                // non DDS is the currently active sub, set primary visual for it
+                ViewStub stub = mDialogView.findViewById(R.id.secondary_mobile_network_stub);
+                if (stub != null) {
+                    stub.inflate();
+                }
+                mSecondaryMobileNetworkLayout = findViewById(R.id.secondary_mobile_network_layout);
+                mSecondaryMobileNetworkLayout.setOnClickListener(
+                        this::onClickConnectedSecondarySub);
+                mSecondaryMobileNetworkLayout.setBackground(mBackgroundOn);
+
+                mSecondaryMobileTitleText = mDialogView.requireViewById(
+                        R.id.secondary_mobile_title);
+                mSecondaryMobileTitleText.setText(getMobileNetworkTitle(autoSwitchNonDdsSubId));
+                mSecondaryMobileTitleText.setTextAppearance(
+                        R.style.TextAppearance_InternetDialog_Active);
+
+                mSecondaryMobileSummaryText =
+                        mDialogView.requireViewById(R.id.secondary_mobile_summary);
+                summary = getMobileNetworkSummary(autoSwitchNonDdsSubId);
+                if (!TextUtils.isEmpty(summary)) {
+                    mSecondaryMobileSummaryText.setText(
+                            Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY));
+                    mSecondaryMobileSummaryText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
+                    mSecondaryMobileSummaryText.setTextAppearance(
+                            R.style.TextAppearance_InternetDialog_Active);
+                }
+
+                ImageView mSecondarySignalIcon =
+                        mDialogView.requireViewById(R.id.secondary_signal_icon);
+                mBackgroundExecutor.execute(() -> {
+                    Drawable drawable = getSignalStrengthDrawable(autoSwitchNonDdsSubId);
+                    mHandler.post(() -> {
+                        mSecondarySignalIcon.setImageDrawable(drawable);
+                    });
+                });
+
+                ImageView mSecondaryMobileSettingsIcon =
+                        mDialogView.requireViewById(R.id.secondary_settings_icon);
+                mSecondaryMobileSettingsIcon.setColorFilter(
+                        mContext.getColor(R.color.connected_network_primary_color));
+
+                // set secondary visual for default data sub
+                mMobileNetworkLayout.setBackground(mBackgroundOff);
+                mMobileTitleText.setTextAppearance(R.style.TextAppearance_InternetDialog);
+                mMobileSummaryText.setTextAppearance(
+                        R.style.TextAppearance_InternetDialog_Secondary);
+                mSignalIcon.setColorFilter(
+                        mContext.getColor(R.color.connected_network_secondary_color));
+            } else {
+                mMobileNetworkLayout.setBackground(
+                        isNetworkConnected ? mBackgroundOn : mBackgroundOff);
+                mMobileTitleText.setTextAppearance(isNetworkConnected
+                        ?
+                        R.style.TextAppearance_InternetDialog_Active
+                        : R.style.TextAppearance_InternetDialog);
+                mMobileSummaryText.setTextAppearance(secondaryRes);
+            }
+
+            if (mSecondaryMobileNetworkLayout != null) {
+                mSecondaryMobileNetworkLayout.setVisibility(nonDdsVisibility);
+            }
+
+            // Set airplane mode to the summary for carrier network
+            if (mInternetDialogController.isAirplaneModeEnabled()) {
+                mAirplaneModeSummaryText.setVisibility(View.VISIBLE);
+                mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode));
+                mAirplaneModeSummaryText.setTextAppearance(secondaryRes);
+            } else {
+                mAirplaneModeSummaryText.setVisibility(View.GONE);
+            }
         }
     }
 
@@ -474,6 +552,10 @@
                 mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry));
         mWifiSettingsIcon.setColorFilter(
                 mContext.getColor(R.color.connected_network_primary_color));
+
+        if (mSecondaryMobileNetworkLayout != null) {
+            mSecondaryMobileNetworkLayout.setVisibility(View.GONE);
+        }
     }
 
     @MainThread
@@ -544,6 +626,11 @@
         mInternetDialogController.launchWifiDetailsSetting(mConnectedWifiEntry.getKey(), view);
     }
 
+    /** For DSDS auto data switch **/
+    void onClickConnectedSecondarySub(View view) {
+        mInternetDialogController.launchMobileNetworkSettings(view);
+    }
+
     void onClickSeeMoreButton(View view) {
         mInternetDialogController.launchNetworkSetting(view);
     }
@@ -558,16 +645,16 @@
                 mIsProgressBarVisible && !mIsSearchingHidden);
     }
 
-    private Drawable getSignalStrengthDrawable() {
-        return mInternetDialogController.getSignalStrengthDrawable();
+    private Drawable getSignalStrengthDrawable(int subId) {
+        return mInternetDialogController.getSignalStrengthDrawable(subId);
     }
 
-    CharSequence getMobileNetworkTitle() {
-        return mInternetDialogController.getMobileNetworkTitle();
+    CharSequence getMobileNetworkTitle(int subId) {
+        return mInternetDialogController.getMobileNetworkTitle(subId);
     }
 
-    String getMobileNetworkSummary() {
-        return mInternetDialogController.getMobileNetworkSummary();
+    String getMobileNetworkSummary(int subId) {
+        return mInternetDialogController.getMobileNetworkSummary(subId);
     }
 
     protected void showProgressBar() {
@@ -605,8 +692,8 @@
     }
 
     private void showTurnOffMobileDialog() {
-        CharSequence carrierName = getMobileNetworkTitle();
-        boolean isInService = mInternetDialogController.isVoiceStateInService();
+        CharSequence carrierName = getMobileNetworkTitle(mDefaultDataSubId);
+        boolean isInService = mInternetDialogController.isVoiceStateInService(mDefaultDataSubId);
         if (TextUtils.isEmpty(carrierName) || !isInService) {
             carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier);
         }
@@ -630,7 +717,33 @@
         SystemUIDialog.setShowForAllUsers(mAlertDialog, true);
         SystemUIDialog.registerDismissListener(mAlertDialog);
         SystemUIDialog.setWindowOnTop(mAlertDialog, mKeyguard.isShowing());
-        mAlertDialog.show();
+        mDialogLaunchAnimator.showFromDialog(mAlertDialog, this, null, false);
+    }
+
+    private void showTurnOffAutoDataSwitchDialog(int subId) {
+        CharSequence carrierName = getMobileNetworkTitle(mDefaultDataSubId);
+        if (TextUtils.isEmpty(carrierName)) {
+            carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier);
+        }
+        mAlertDialog = new Builder(mContext)
+                .setTitle(mContext.getString(R.string.auto_data_switch_disable_title, carrierName))
+                .setMessage(R.string.auto_data_switch_disable_message)
+                .setNegativeButton(R.string.auto_data_switch_dialog_negative_button,
+                        (d, w) -> {})
+                .setPositiveButton(R.string.auto_data_switch_dialog_positive_button,
+                        (d, w) -> {
+                            mInternetDialogController
+                                    .setAutoDataSwitchMobileDataPolicy(subId, false);
+                            if (mSecondaryMobileNetworkLayout != null) {
+                                mSecondaryMobileNetworkLayout.setVisibility(View.GONE);
+                            }
+                        })
+                .create();
+        mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        SystemUIDialog.setShowForAllUsers(mAlertDialog, true);
+        SystemUIDialog.registerDismissListener(mAlertDialog);
+        SystemUIDialog.setWindowOnTop(mAlertDialog, mKeyguard.isShowing());
+        mDialogLaunchAnimator.showFromDialog(mAlertDialog, this, null, false);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 9c0a087..4c7f10e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -37,6 +37,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.wifi.WifiManager;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -78,6 +79,8 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 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.plugins.ActivityStarter;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -90,6 +93,7 @@
 import com.android.wifitrackerlib.WifiEntry;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -113,6 +117,17 @@
             "android.settings.NETWORK_PROVIDER_SETTINGS";
     private static final String ACTION_WIFI_SCANNING_SETTINGS =
             "android.settings.WIFI_SCANNING_SETTINGS";
+    /**
+     * Fragment "key" argument passed thru {@link #SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS}
+     */
+    private static final String SETTINGS_EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+    /**
+     * When starting this activity, this extra can also be specified to supply a Bundle of arguments
+     * to pass to that fragment when it is instantiated during the initial creation of the activity.
+     */
+    private static final String SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS =
+            ":settings:show_fragment_args";
+    private static final String AUTO_DATA_SWITCH_SETTING_R_ID = "auto_data_switch";
     public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
     public static final int NO_CELL_DATA_TYPE_ICON = 0;
     private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off;
@@ -130,9 +145,12 @@
 
     static final int MAX_WIFI_ENTRY_COUNT = 3;
 
+    private final FeatureFlags mFeatureFlags;
+
     private WifiManager mWifiManager;
     private Context mContext;
     private SubscriptionManager mSubscriptionManager;
+    private Map<Integer, TelephonyManager> mSubIdTelephonyManagerMap = new HashMap<>();
     private TelephonyManager mTelephonyManager;
     private ConnectivityManager mConnectivityManager;
     private CarrierConfigTracker mCarrierConfigTracker;
@@ -155,6 +173,7 @@
     private WindowManager mWindowManager;
     private ToastFactory mToastFactory;
     private SignalDrawable mSignalDrawable;
+    private SignalDrawable mSecondarySignalDrawable; // For the secondary mobile data sub in DSDS
     private LocationController mLocationController;
     private DialogLaunchAnimator mDialogLaunchAnimator;
     private boolean mHasWifiEntries;
@@ -213,7 +232,8 @@
             CarrierConfigTracker carrierConfigTracker,
             LocationController locationController,
             DialogLaunchAnimator dialogLaunchAnimator,
-            WifiStateWorker wifiStateWorker
+            WifiStateWorker wifiStateWorker,
+            FeatureFlags featureFlags
     ) {
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialogController");
@@ -242,10 +262,12 @@
         mWindowManager = windowManager;
         mToastFactory = toastFactory;
         mSignalDrawable = new SignalDrawable(mContext);
+        mSecondarySignalDrawable = new SignalDrawable(mContext);
         mLocationController = locationController;
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mConnectedWifiInternetMonitor = new ConnectedWifiInternetMonitor();
         mWifiStateWorker = wifiStateWorker;
+        mFeatureFlags = featureFlags;
     }
 
     void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -267,6 +289,7 @@
         }
         mConfig = MobileMappings.Config.readConfig(mContext);
         mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
+        mSubIdTelephonyManagerMap.put(mDefaultDataSubId, mTelephonyManager);
         mInternetTelephonyCallback = new InternetTelephonyCallback();
         mTelephonyManager.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback);
         // Listen the connectivity changes
@@ -280,7 +303,9 @@
             Log.d(TAG, "onStop");
         }
         mBroadcastDispatcher.unregisterReceiver(mConnectionStateReceiver);
-        mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback);
+        for (TelephonyManager tm : mSubIdTelephonyManagerMap.values()) {
+            tm.unregisterTelephonyCallback(mInternetTelephonyCallback);
+        }
         mSubscriptionManager.removeOnSubscriptionsChangedListener(
                 mOnSubscriptionsChangedListener);
         mAccessPointController.removeAccessPointCallback(this);
@@ -371,7 +396,10 @@
         if (DEBUG) {
             Log.d(TAG, "No Wi-Fi item.");
         }
-        if (!hasActiveSubId() || (!isVoiceStateInService() && !isDataStateInService())) {
+        boolean isActiveOnNonDds = getActiveAutoSwitchNonDdsSubId() != SubscriptionManager
+                .INVALID_SUBSCRIPTION_ID;
+        if (!hasActiveSubId() || (!isVoiceStateInService(mDefaultDataSubId)
+                && !isDataStateInService(mDefaultDataSubId) && !isActiveOnNonDds)) {
             if (DEBUG) {
                 Log.d(TAG, "No carrier or service is out of service.");
             }
@@ -412,7 +440,7 @@
         return drawable;
     }
 
-    Drawable getSignalStrengthDrawable() {
+    Drawable getSignalStrengthDrawable(int subId) {
         Drawable drawable = mContext.getDrawable(
                 R.drawable.ic_signal_strength_zero_bar_no_internet);
         try {
@@ -424,9 +452,10 @@
             }
 
             boolean isCarrierNetworkActive = isCarrierNetworkActive();
-            if (isDataStateInService() || isVoiceStateInService() || isCarrierNetworkActive) {
+            if (isDataStateInService(subId) || isVoiceStateInService(subId)
+                    || isCarrierNetworkActive) {
                 AtomicReference<Drawable> shared = new AtomicReference<>();
-                shared.set(getSignalStrengthDrawableWithLevel(isCarrierNetworkActive));
+                shared.set(getSignalStrengthDrawableWithLevel(isCarrierNetworkActive, subId));
                 drawable = shared.get();
             }
 
@@ -447,24 +476,30 @@
      *
      * @return The Drawable which is a signal bar icon with level.
      */
-    Drawable getSignalStrengthDrawableWithLevel(boolean isCarrierNetworkActive) {
-        final SignalStrength strength = mTelephonyManager.getSignalStrength();
+    Drawable getSignalStrengthDrawableWithLevel(boolean isCarrierNetworkActive, int subId) {
+        TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager);
+        final SignalStrength strength = tm.getSignalStrength();
         int level = (strength == null) ? 0 : strength.getLevel();
         int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
         if (isCarrierNetworkActive) {
             level = getCarrierNetworkLevel();
             numLevels = WifiEntry.WIFI_LEVEL_MAX + 1;
-        } else if (mSubscriptionManager != null && shouldInflateSignalStrength(mDefaultDataSubId)) {
+        } else if (mSubscriptionManager != null && shouldInflateSignalStrength(subId)) {
             level += 1;
             numLevels += 1;
         }
-        return getSignalStrengthIcon(mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON,
+        return getSignalStrengthIcon(subId, mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON,
                 !isMobileDataEnabled());
     }
 
-    Drawable getSignalStrengthIcon(Context context, int level, int numLevels,
+    Drawable getSignalStrengthIcon(int subId, Context context, int level, int numLevels,
             int iconType, boolean cutOut) {
-        mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
+        boolean isForDds = subId == mDefaultDataSubId;
+        if (isForDds) {
+            mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
+        } else {
+            mSecondarySignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
+        }
 
         // Make the network type drawable
         final Drawable networkDrawable =
@@ -473,7 +508,8 @@
                         : context.getResources().getDrawable(iconType, context.getTheme());
 
         // Overlay the two drawables
-        final Drawable[] layers = {networkDrawable, mSignalDrawable};
+        final Drawable[] layers = {networkDrawable, isForDds
+                ? mSignalDrawable : mSecondarySignalDrawable};
         final int iconSize =
                 context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
 
@@ -571,14 +607,39 @@
                 info -> info.uniqueName));
     }
 
-    CharSequence getMobileNetworkTitle() {
-        return getUniqueSubscriptionDisplayName(mDefaultDataSubId, mContext);
+    /**
+     * @return the subId of the visible non-DDS if it's actively being used for data, otherwise
+     * return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+     */
+    int getActiveAutoSwitchNonDdsSubId() {
+        if (!mFeatureFlags.isEnabled(Flags.QS_SECONDARY_DATA_SUB_INFO)) {
+            // sets the non-DDS to be not found to hide its visual
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+        SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(
+                SubscriptionManager.getActiveDataSubscriptionId());
+        if (subInfo != null && subInfo.getSubscriptionId() != mDefaultDataSubId
+                && !subInfo.isOpportunistic()) {
+            int subId = subInfo.getSubscriptionId();
+            if (mSubIdTelephonyManagerMap.get(subId) == null) {
+                TelephonyManager secondaryTm = mTelephonyManager.createForSubscriptionId(subId);
+                secondaryTm.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback);
+                mSubIdTelephonyManagerMap.put(subId, secondaryTm);
+            }
+            return subId;
+        }
+        return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
     }
 
-    String getMobileNetworkSummary() {
+    CharSequence getMobileNetworkTitle(int subId) {
+        return getUniqueSubscriptionDisplayName(subId, mContext);
+    }
+
+    String getMobileNetworkSummary(int subId) {
         String description = getNetworkTypeDescription(mContext, mConfig,
-                mTelephonyDisplayInfo, mDefaultDataSubId);
-        return getMobileSummary(mContext, description);
+                mTelephonyDisplayInfo, subId);
+        return getMobileSummary(mContext, description, subId);
     }
 
     /**
@@ -606,22 +667,28 @@
                 ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : "";
     }
 
-    private String getMobileSummary(Context context, String networkTypeDescription) {
+    private String getMobileSummary(Context context, String networkTypeDescription, int subId) {
         if (!isMobileDataEnabled()) {
             return context.getString(R.string.mobile_data_off_summary);
         }
 
         String summary = networkTypeDescription;
+        boolean isForDds = subId == mDefaultDataSubId;
+        int activeSubId = getActiveAutoSwitchNonDdsSubId();
+        boolean isOnNonDds = activeSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         // Set network description for the carrier network when connecting to the carrier network
         // under the airplane mode ON.
         if (activeNetworkIsCellular() || isCarrierNetworkActive()) {
             summary = context.getString(R.string.preference_summary_default_combination,
-                    context.getString(R.string.mobile_data_connection_active),
+                    context.getString(
+                            isForDds // if nonDds is active, explains Dds status as poor connection
+                                    ? (isOnNonDds ? R.string.mobile_data_poor_connection
+                                            : R.string.mobile_data_connection_active)
+                            : R.string.mobile_data_temp_connection_active),
                     networkTypeDescription);
-        } else if (!isDataStateInService()) {
+        } else if (!isDataStateInService(subId)) {
             summary = context.getString(R.string.mobile_data_no_connection);
         }
-
         return summary;
     }
 
@@ -647,6 +714,26 @@
         }
     }
 
+    void launchMobileNetworkSettings(View view) {
+        final int subId = getActiveAutoSwitchNonDdsSubId();
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            Log.w(TAG, "launchMobileNetworkSettings fail, invalid subId:" + subId);
+            return;
+        }
+        startActivity(getSubSettingIntent(subId), view);
+    }
+
+    Intent getSubSettingIntent(int subId) {
+        final Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
+
+        final Bundle fragmentArgs = new Bundle();
+        // Special contract for Settings to highlight permission row
+        fragmentArgs.putString(SETTINGS_EXTRA_FRAGMENT_ARG_KEY, AUTO_DATA_SWITCH_SETTING_R_ID);
+        fragmentArgs.putInt(Settings.EXTRA_SUB_ID, subId);
+        intent.putExtra(SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
+        return intent;
+    }
+
     void launchWifiScanningSetting(View view) {
         final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -796,8 +883,20 @@
         mWorkerHandler.post(() -> setMergedCarrierWifiEnabledIfNeed(subId, enabled));
     }
 
-    boolean isDataStateInService() {
-        final ServiceState serviceState = mTelephonyManager.getServiceState();
+    void setAutoDataSwitchMobileDataPolicy(int subId, boolean enable) {
+        TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager);
+        if (tm == null) {
+            if (DEBUG) {
+                Log.d(TAG, "TelephonyManager is null, can not set mobile data.");
+            }
+            return;
+        }
+        tm.setMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, enable);
+    }
+
+    boolean isDataStateInService(int subId) {
+        TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager);
+        final ServiceState serviceState = tm.getServiceState();
         NetworkRegistrationInfo regInfo =
                 (serviceState == null) ? null : serviceState.getNetworkRegistrationInfo(
                         NetworkRegistrationInfo.DOMAIN_PS,
@@ -805,7 +904,7 @@
         return (regInfo == null) ? false : regInfo.isRegistered();
     }
 
-    boolean isVoiceStateInService() {
+    boolean isVoiceStateInService(int subId) {
         if (mTelephonyManager == null) {
             if (DEBUG) {
                 Log.d(TAG, "TelephonyManager is null, can not detect voice state.");
@@ -813,7 +912,8 @@
             return false;
         }
 
-        final ServiceState serviceState = mTelephonyManager.getServiceState();
+        TelephonyManager tm = mSubIdTelephonyManagerMap.getOrDefault(subId, mTelephonyManager);
+        final ServiceState serviceState = tm.getServiceState();
         return serviceState != null
                 && serviceState.getState() == serviceState.STATE_IN_SERVICE;
     }
@@ -1104,6 +1204,7 @@
         if (SubscriptionManager.isUsableSubscriptionId(mDefaultDataSubId)) {
             mTelephonyManager.unregisterTelephonyCallback(mInternetTelephonyCallback);
             mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
+            mSubIdTelephonyManagerMap.put(mDefaultDataSubId, mTelephonyManager);
             mTelephonyManager.registerTelephonyCallback(mHandler::post,
                     mInternetTelephonyCallback);
             mCallback.onSubscriptionsChanged(mDefaultDataSubId);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index 8566ca3..796672d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -66,7 +66,8 @@
         } else {
             internetDialog = InternetDialog(
                 context, this, internetDialogController,
-                canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
+                canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger,
+                    dialogLaunchAnimator, handler,
                 executor, keyguardStateController
             )
             if (view != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index ba97297..547b496 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -78,8 +78,8 @@
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.util.ScreenshotHelper;
 import com.android.systemui.Dumpable;
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -90,12 +90,11 @@
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.navigationbar.buttons.KeyButtonView;
 import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -108,20 +107,19 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
 import javax.inject.Inject;
 
 import dagger.Lazy;
 
-
 /**
  * Class to send information from overview to launcher with a binder.
  */
 @SysUISingleton
-public class OverviewProxyService extends CurrentUserTracker implements
-        CallbackController<OverviewProxyListener>, NavigationModeController.ModeChangedListener,
-        Dumpable {
+public class OverviewProxyService implements CallbackController<OverviewProxyListener>,
+        NavigationModeController.ModeChangedListener, Dumpable {
 
     private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
 
@@ -133,6 +131,7 @@
     private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
 
     private final Context mContext;
+    private final Executor mMainExecutor;
     private final ShellInterface mShellInterface;
     private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
     private SysUiState mSysUiState;
@@ -145,6 +144,7 @@
     private final Intent mQuickStepIntent;
     private final ScreenshotHelper mScreenshotHelper;
     private final CommandQueue mCommandQueue;
+    private final UserTracker mUserTracker;
     private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController;
     private final UiEventLogger mUiEventLogger;
 
@@ -417,7 +417,7 @@
                 return;
             }
 
-            mCurrentBoundedUserId = getCurrentUserId();
+            mCurrentBoundedUserId = mUserTracker.getUserId();
             mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
 
             Bundle params = new Bundle();
@@ -498,34 +498,44 @@
         }
     };
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    mConnectionBackoffAttempts = 0;
+                    internalConnectToCurrentUser();
+                }
+            };
+
     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
     @Inject
     public OverviewProxyService(Context context,
+            @Main Executor mainExecutor,
             CommandQueue commandQueue,
             ShellInterface shellInterface,
             Lazy<NavigationBarController> navBarControllerLazy,
             Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
             NavigationModeController navModeController,
             NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
-            BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
             ScreenLifecycle screenLifecycle,
             UiEventLogger uiEventLogger,
             KeyguardUnlockAnimationController sysuiUnlockAnimationController,
             AssistUtils assistUtils,
             DumpManager dumpManager) {
-        super(broadcastDispatcher);
-
         // b/241601880: This component shouldn't be running for a non-primary user
         if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) {
             Log.e(TAG_OPS, "Unexpected initialization for non-primary user", new Throwable());
         }
 
         mContext = context;
+        mMainExecutor = mainExecutor;
         mShellInterface = shellInterface;
         mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
         mHandler = new Handler();
         mNavBarControllerLazy = navBarControllerLazy;
         mStatusBarWinController = statusBarWinController;
+        mUserTracker = userTracker;
         mConnectionBackoffAttempts = 0;
         mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
                 com.android.internal.R.string.config_recentsComponentName));
@@ -566,7 +576,7 @@
         mCommandQueue = commandQueue;
 
         // Listen for user setup
-        startTracking();
+        mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
 
         screenLifecycle.addObserver(mLifecycleObserver);
 
@@ -579,12 +589,6 @@
         assistUtils.registerVoiceInteractionSessionListener(mVoiceInteractionSessionListener);
     }
 
-    @Override
-    public void onUserSwitched(int newUserId) {
-        mConnectionBackoffAttempts = 0;
-        internalConnectToCurrentUser();
-    }
-
     public void onVoiceSessionWindowVisibilityChanged(boolean visible) {
         mSysUiState.setFlag(SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING, visible)
                 .commitUpdate(mContext.getDisplayId());
@@ -712,7 +716,7 @@
             mBound = mContext.bindServiceAsUser(launcherServiceIntent,
                     mOverviewServiceConnection,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
-                    UserHandle.of(getCurrentUserId()));
+                    UserHandle.of(mUserTracker.getUserId()));
         } catch (SecurityException e) {
             Log.e(TAG_OPS, "Unable to bind because of security error", e);
         }
@@ -941,7 +945,7 @@
     }
 
     private void updateEnabledState() {
-        final int currentUser = ActivityManagerWrapper.getInstance().getCurrentUserId();
+        final int currentUser = mUserTracker.getUserId();
         mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
                 MATCH_SYSTEM_ONLY, currentUser) != null;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt b/packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
deleted file mode 100644
index 6de4648..0000000
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.ripple
-
-/** A common utility functions that are used for computing [RippleShader]. */
-class RippleShaderUtilLibrary {
-    //language=AGSL
-    companion object {
-        const val SHADER_LIB = """
-            float triangleNoise(vec2 n) {
-                    n  = fract(n * vec2(5.3987, 5.4421));
-                    n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
-                    float xy = n.x * n.y;
-                    return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
-                }
-                const float PI = 3.1415926535897932384626;
-
-                float sparkles(vec2 uv, float t) {
-                    float n = triangleNoise(uv);
-                    float s = 0.0;
-                    for (float i = 0; i < 4; i += 1) {
-                        float l = i * 0.01;
-                        float h = l + 0.1;
-                        float o = smoothstep(n - l, h, n);
-                        o *= abs(sin(PI * o * (t + 0.55 * i)));
-                        s += o;
-                    }
-                    return s;
-                }
-
-                vec2 distort(vec2 p, float time, float distort_amount_radial,
-                    float distort_amount_xy) {
-                        float angle = atan(p.y, p.x);
-                          return p + vec2(sin(angle * 8 + time * 0.003 + 1.641),
-                                    cos(angle * 5 + 2.14 + time * 0.00412)) * distort_amount_radial
-                             + vec2(sin(p.x * 0.01 + time * 0.00215 + 0.8123),
-                                    cos(p.y * 0.01 + time * 0.005931)) * distort_amount_xy;
-            }"""
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index cffd28f..19bb15a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -24,8 +24,9 @@
 import android.os.Looper
 import android.os.ResultReceiver
 import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
 import android.widget.AdapterView
-import android.widget.AdapterView.OnItemClickListener
 import android.widget.ArrayAdapter
 import android.widget.Spinner
 import android.widget.Switch
@@ -47,6 +48,7 @@
     private val onStartRecordingClicked: Runnable?
 ) : BaseScreenSharePermissionDialog(context, createOptionList(), null) {
     private lateinit var tapsSwitch: Switch
+    private lateinit var tapsView: View
     private lateinit var audioSwitch: Switch
     private lateinit var options: Spinner
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -84,16 +86,25 @@
     private fun initRecordOptionsView() {
         audioSwitch = findViewById(R.id.screenrecord_audio_switch)
         tapsSwitch = findViewById(R.id.screenrecord_taps_switch)
+        tapsView = findViewById(R.id.show_taps)
+        updateTapsViewVisibility()
         options = findViewById(R.id.screen_recording_options)
         val a: ArrayAdapter<*> =
             ScreenRecordingAdapter(context, android.R.layout.simple_spinner_dropdown_item, MODES)
         a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
         options.adapter = a
-        options.setOnItemClickListenerInt(
-            OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, _: Long ->
-                audioSwitch.isChecked = true
-            }
-        )
+        options.setOnItemClickListenerInt { _: AdapterView<*>?, _: View?, _: Int, _: Long ->
+            audioSwitch.isChecked = true
+        }
+    }
+
+    override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) {
+        super.onItemSelected(adapterView, view, pos, id)
+        updateTapsViewVisibility()
+    }
+
+    private fun updateTapsViewVisibility() {
+        tapsView.visibility = if (selectedScreenShareOption.mode == SINGLE_APP) GONE else VISIBLE
     }
 
     /**
@@ -103,7 +114,7 @@
      */
     private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
         val userContext = userContextProvider.userContext
-        val showTaps = tapsSwitch.isChecked
+        val showTaps = selectedScreenShareOption.mode != SINGLE_APP && tapsSwitch.isChecked
         val audioMode =
             if (audioSwitch.isChecked) options.selectedItem as ScreenRecordingAudioSource
             else ScreenRecordingAudioSource.NONE
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index 5961635..01e32b7a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -32,7 +32,7 @@
 import com.android.internal.infra.ServiceConnector
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
 import javax.inject.Inject
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineDispatcher
@@ -45,7 +45,7 @@
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    @Background private val bgDispatcher: CoroutineDispatcher,
+    @Main private val mainDispatcher: CoroutineDispatcher,
     private val context: Context,
 ) {
     /**
@@ -70,23 +70,21 @@
         userId: Int,
         overrideTransition: Boolean,
     ) {
-        withContext(bgDispatcher) {
-            dismissKeyguard()
+        dismissKeyguard()
 
-            if (userId == UserHandle.myUserId()) {
-                context.startActivity(intent, bundle)
-            } else {
-                launchCrossProfileIntent(userId, intent, bundle)
-            }
+        if (userId == UserHandle.myUserId()) {
+            withContext(mainDispatcher) { context.startActivity(intent, bundle) }
+        } else {
+            launchCrossProfileIntent(userId, intent, bundle)
+        }
 
-            if (overrideTransition) {
-                val runner = RemoteAnimationAdapter(SCREENSHOT_REMOTE_RUNNER, 0, 0)
-                try {
-                    WindowManagerGlobal.getWindowManagerService()
-                        .overridePendingAppTransitionRemote(runner, Display.DEFAULT_DISPLAY)
-                } catch (e: Exception) {
-                    Log.e(TAG, "Error overriding screenshot app transition", e)
-                }
+        if (overrideTransition) {
+            val runner = RemoteAnimationAdapter(SCREENSHOT_REMOTE_RUNNER, 0, 0)
+            try {
+                WindowManagerGlobal.getWindowManagerService()
+                    .overridePendingAppTransitionRemote(runner, Display.DEFAULT_DISPLAY)
+            } catch (e: Exception) {
+                Log.e(TAG, "Error overriding screenshot app transition", e)
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 8bf956b..5450db9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -46,6 +46,8 @@
 import com.android.systemui.R;
 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.screenshot.ScrollCaptureController.LongScreenshot;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -67,6 +69,7 @@
     private static final String TAG = LogConfig.logTag(LongScreenshotActivity.class);
 
     public static final String EXTRA_CAPTURE_RESPONSE = "capture-response";
+    public static final String EXTRA_SCREENSHOT_USER_HANDLE = "screenshot-userhandle";
     private static final String KEY_SAVED_IMAGE_PATH = "saved-image-path";
 
     private final UiEventLogger mUiEventLogger;
@@ -74,6 +77,8 @@
     private final Executor mBackgroundExecutor;
     private final ImageExporter mImageExporter;
     private final LongScreenshotData mLongScreenshotHolder;
+    private final ActionIntentExecutor mActionExecutor;
+    private final FeatureFlags mFeatureFlags;
 
     private ImageView mPreview;
     private ImageView mTransitionView;
@@ -85,6 +90,7 @@
     private CropView mCropView;
     private MagnifierView mMagnifierView;
     private ScrollCaptureResponse mScrollCaptureResponse;
+    private UserHandle mScreenshotUserHandle;
     private File mSavedImagePath;
 
     private ListenableFuture<File> mCacheSaveFuture;
@@ -103,12 +109,15 @@
     @Inject
     public LongScreenshotActivity(UiEventLogger uiEventLogger, ImageExporter imageExporter,
             @Main Executor mainExecutor, @Background Executor bgExecutor,
-            LongScreenshotData longScreenshotHolder) {
+            LongScreenshotData longScreenshotHolder, ActionIntentExecutor actionExecutor,
+            FeatureFlags featureFlags) {
         mUiEventLogger = uiEventLogger;
         mUiExecutor = mainExecutor;
         mBackgroundExecutor = bgExecutor;
         mImageExporter = imageExporter;
         mLongScreenshotHolder = longScreenshotHolder;
+        mActionExecutor = actionExecutor;
+        mFeatureFlags = featureFlags;
     }
 
 
@@ -139,6 +148,11 @@
 
         Intent intent = getIntent();
         mScrollCaptureResponse = intent.getParcelableExtra(EXTRA_CAPTURE_RESPONSE);
+        mScreenshotUserHandle = intent.getParcelableExtra(EXTRA_SCREENSHOT_USER_HANDLE,
+                UserHandle.class);
+        if (mScreenshotUserHandle == null) {
+            mScreenshotUserHandle = Process.myUserHandle();
+        }
 
         if (savedInstanceState != null) {
             String savedImagePath = savedInstanceState.getString(KEY_SAVED_IMAGE_PATH);
@@ -318,36 +332,51 @@
     }
 
     private void doEdit(Uri uri) {
-        String editorPackage = getString(R.string.config_screenshotEditor);
-        Intent intent = new Intent(Intent.ACTION_EDIT);
-        if (!TextUtils.isEmpty(editorPackage)) {
-            intent.setComponent(ComponentName.unflattenFromString(editorPackage));
-        }
-        intent.setDataAndType(uri, "image/png");
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY) && mScreenshotUserHandle
+                != Process.myUserHandle()) {
+            // TODO: Fix transition for work profile. Omitting it in the meantime.
+            mActionExecutor.launchIntentAsync(
+                    ActionIntentCreator.INSTANCE.createEditIntent(uri, this),
+                    null,
+                    mScreenshotUserHandle.getIdentifier(), false);
+        } else {
+            String editorPackage = getString(R.string.config_screenshotEditor);
+            Intent intent = new Intent(Intent.ACTION_EDIT);
+            if (!TextUtils.isEmpty(editorPackage)) {
+                intent.setComponent(ComponentName.unflattenFromString(editorPackage));
+            }
+            intent.setDataAndType(uri, "image/png");
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
-        mTransitionView.setImageBitmap(mOutputBitmap);
-        mTransitionView.setVisibility(View.VISIBLE);
-        mTransitionView.setTransitionName(
-                ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
-        // TODO: listen for transition completing instead of finishing onStop
-        mTransitionStarted = true;
-        startActivity(intent,
-                ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
-                        ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle());
+            mTransitionView.setImageBitmap(mOutputBitmap);
+            mTransitionView.setVisibility(View.VISIBLE);
+            mTransitionView.setTransitionName(
+                    ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+            // TODO: listen for transition completing instead of finishing onStop
+            mTransitionStarted = true;
+            startActivity(intent,
+                    ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
+                            ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle());
+        }
     }
 
     private void doShare(Uri uri) {
-        Intent intent = new Intent(Intent.ACTION_SEND);
-        intent.setType("image/png");
-        intent.putExtra(Intent.EXTRA_STREAM, uri);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        Intent sharingChooserIntent = Intent.createChooser(intent, null)
-                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)) {
+            Intent shareIntent = ActionIntentCreator.INSTANCE.createShareIntent(uri, null);
+            mActionExecutor.launchIntentAsync(shareIntent, null,
+                    mScreenshotUserHandle.getIdentifier(), false);
+        } else {
+            Intent intent = new Intent(Intent.ACTION_SEND);
+            intent.setType("image/png");
+            intent.putExtra(Intent.EXTRA_STREAM, uri);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                    | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            Intent sharingChooserIntent = Intent.createChooser(intent, null)
+                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-        startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
+            startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
+        }
     }
 
     private void onClicked(View v) {
@@ -389,8 +418,8 @@
         mOutputBitmap = renderBitmap(drawable, bounds);
         ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
                 mBackgroundExecutor, UUID.randomUUID(), mOutputBitmap, ZonedDateTime.now(),
-                // TODO: Owner must match the owner of the captured window.
-                Process.myUserHandle());
+                mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)
+                        ? mScreenshotUserHandle : Process.myUserHandle());
         exportFuture.addListener(() -> onExportCompleted(action, exportFuture), mUiExecutor);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 7143ba2..b4934cf 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -38,6 +38,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -81,7 +82,6 @@
 
     private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
     private String mScreenshotId;
-    private final boolean mSmartActionsEnabled;
     private final Random mRandom = new Random();
     private final Supplier<ActionTransition> mSharedElementTransition;
     private final ImageExporter mImageExporter;
@@ -109,8 +109,6 @@
         mParams = data;
 
         // Initialize screenshot notification smart actions provider.
-        mSmartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, true);
         mSmartActionsProvider = screenshotNotificationSmartActionsProvider;
     }
 
@@ -131,8 +129,16 @@
 
         Bitmap image = mParams.image;
         mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId);
+
+        boolean savingToOtherUser = mFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)
+                && (user != Process.myUserHandle());
+        // Smart actions don't yet work for cross-user saves.
+        boolean smartActionsEnabled = !savingToOtherUser
+                && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS,
+                true);
         try {
-            if (mSmartActionsEnabled && mParams.mQuickShareActionsReadyListener != null) {
+            if (smartActionsEnabled && mParams.mQuickShareActionsReadyListener != null) {
                 // Since Quick Share target recommendation does not rely on image URL, it is
                 // queried and surfaced before image compress/export. Action intent would not be
                 // used, because it does not contain image URL.
@@ -150,10 +156,9 @@
             CompletableFuture<List<Notification.Action>> smartActionsFuture =
                     mScreenshotSmartActions.getSmartActionsFuture(
                             mScreenshotId, uri, image, mSmartActionsProvider, REGULAR_SMART_ACTIONS,
-                            mSmartActionsEnabled, user);
-
+                            smartActionsEnabled, user);
             List<Notification.Action> smartActions = new ArrayList<>();
-            if (mSmartActionsEnabled) {
+            if (smartActionsEnabled) {
                 int timeoutMs = DeviceConfig.getInt(
                         DeviceConfig.NAMESPACE_SYSTEMUI,
                         SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
@@ -168,9 +173,12 @@
             mImageData.uri = uri;
             mImageData.owner = user;
             mImageData.smartActions = smartActions;
-            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
-            mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
-            mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
+            mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri,
+                    smartActionsEnabled);
+            mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri,
+                    smartActionsEnabled);
+            mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri,
+                    smartActionsEnabled);
             mImageData.quickShareAction = createQuickShareAction(mContext,
                     mQuickShareData.quickShareAction, uri);
             mImageData.subject = getSubjectString();
@@ -228,7 +236,8 @@
      * Assumes that the action intent is sent immediately after being supplied.
      */
     @VisibleForTesting
-    Supplier<ActionTransition> createShareAction(Context context, Resources r, Uri uri) {
+    Supplier<ActionTransition> createShareAction(Context context, Resources r, Uri uri,
+            boolean smartActionsEnabled) {
         return () -> {
             ActionTransition transition = mSharedElementTransition.get();
 
@@ -274,7 +283,7 @@
                             .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
                             .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
                             .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
-                                    mSmartActionsEnabled)
+                                    smartActionsEnabled)
                             .setAction(Intent.ACTION_SEND)
                             .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
@@ -290,7 +299,8 @@
     }
 
     @VisibleForTesting
-    Supplier<ActionTransition> createEditAction(Context context, Resources r, Uri uri) {
+    Supplier<ActionTransition> createEditAction(Context context, Resources r, Uri uri,
+            boolean smartActionsEnabled) {
         return () -> {
             ActionTransition transition = mSharedElementTransition.get();
             // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
@@ -323,7 +333,7 @@
                             .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
                             .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
                             .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
-                                    mSmartActionsEnabled)
+                                    smartActionsEnabled)
                             .putExtra(ScreenshotController.EXTRA_OVERRIDE_TRANSITION, true)
                             .setAction(Intent.ACTION_EDIT)
                             .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
@@ -339,7 +349,8 @@
     }
 
     @VisibleForTesting
-    Notification.Action createDeleteAction(Context context, Resources r, Uri uri) {
+    Notification.Action createDeleteAction(Context context, Resources r, Uri uri,
+            boolean smartActionsEnabled) {
         // Make sure pending intents for the system user are still unique across users
         // by setting the (otherwise unused) request code to the current user id.
         int requestCode = mContext.getUserId();
@@ -350,7 +361,7 @@
                         .putExtra(ScreenshotController.SCREENSHOT_URI_ID, uri.toString())
                         .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
                         .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
-                                mSmartActionsEnabled)
+                                smartActionsEnabled)
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
                 PendingIntent.FLAG_CANCEL_CURRENT
                         | PendingIntent.FLAG_ONE_SHOT
@@ -391,7 +402,7 @@
             Intent intent = new Intent(context, SmartActionsReceiver.class)
                     .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, action.actionIntent)
                     .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
+            addIntentExtras(mScreenshotId, intent, actionType, true /* smartActionsEnabled */);
             PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
                     mRandom.nextInt(),
                     intent,
@@ -445,7 +456,9 @@
         Intent intent = new Intent(context, SmartActionsReceiver.class)
                 .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, updatedPendingIntent)
                 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
+        // We only query for quick share actions when smart actions are enabled, so we can assert
+        // that it's true here.
+        addIntentExtras(mScreenshotId, intent, actionType, true /* smartActionsEnabled */);
         PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
                 mRandom.nextInt(),
                 intent,
@@ -464,7 +477,7 @@
                 mScreenshotSmartActions.getSmartActionsFuture(
                         mScreenshotId, null, image, mSmartActionsProvider,
                         QUICK_SHARE_ACTION,
-                        mSmartActionsEnabled, user);
+                        true /* smartActionsEnabled */, user);
         int timeoutMs = DeviceConfig.getInt(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index d395bd3..d94c827 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -591,7 +591,7 @@
         // Wait until this window is attached to request because it is
         // the reference used to locate the target window (below).
         withWindowAttached(() -> {
-            requestScrollCapture();
+            requestScrollCapture(owner);
             mWindow.peekDecorView().getViewRootImpl().setActivityConfigCallback(
                     new ViewRootImpl.ActivityConfigCallback() {
                         @Override
@@ -603,11 +603,11 @@
                                 mScreenshotView.hideScrollChip();
                                 // Delay scroll capture eval a bit to allow the underlying activity
                                 // to set up in the new orientation.
-                                mScreenshotHandler.postDelayed(
-                                        ScreenshotController.this::requestScrollCapture, 150);
+                                mScreenshotHandler.postDelayed(() -> {
+                                    requestScrollCapture(owner);
+                                }, 150);
                                 mScreenshotView.updateInsets(
-                                        mWindowManager.getCurrentWindowMetrics()
-                                                .getWindowInsets());
+                                        mWindowManager.getCurrentWindowMetrics().getWindowInsets());
                                 // Screenshot animation calculations won't be valid anymore,
                                 // so just end
                                 if (mScreenshotAnimation != null
@@ -655,7 +655,7 @@
         mScreenshotHandler.cancelTimeout(); // restarted after animation
     }
 
-    private void requestScrollCapture() {
+    private void requestScrollCapture(UserHandle owner) {
         if (!allowLongScreenshots()) {
             Log.d(TAG, "Long screenshots not supported on this device");
             return;
@@ -668,10 +668,11 @@
                 mScrollCaptureClient.request(DEFAULT_DISPLAY);
         mLastScrollCaptureRequest = future;
         mLastScrollCaptureRequest.addListener(() ->
-                onScrollCaptureResponseReady(future), mMainExecutor);
+                onScrollCaptureResponseReady(future, owner), mMainExecutor);
     }
 
-    private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture) {
+    private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture,
+            UserHandle owner) {
         try {
             if (mLastScrollCaptureResponse != null) {
                 mLastScrollCaptureResponse.close();
@@ -701,7 +702,7 @@
                 mScreenshotView.prepareScrollingTransition(response, mScreenBitmap, newScreenshot,
                         mScreenshotTakenInPortrait);
                 // delay starting scroll capture to make sure the scrim is up before the app moves
-                mScreenshotView.post(() -> runBatchScrollCapture(response));
+                mScreenshotView.post(() -> runBatchScrollCapture(response, owner));
             });
         } catch (InterruptedException | ExecutionException e) {
             Log.e(TAG, "requestScrollCapture failed", e);
@@ -710,7 +711,7 @@
 
     ListenableFuture<ScrollCaptureController.LongScreenshot> mLongScreenshotFuture;
 
-    private void runBatchScrollCapture(ScrollCaptureResponse response) {
+    private void runBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) {
         // Clear the reference to prevent close() in dismissScreenshot
         mLastScrollCaptureResponse = null;
 
@@ -744,6 +745,8 @@
                                     longScreenshot));
 
             final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
+            intent.putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE,
+                    owner);
             intent.setFlags(
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 8b5a24c..c891686 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -89,7 +89,9 @@
     @UiEvent(doc = "User has saved a long screenshot to a file")
     SCREENSHOT_LONG_SCREENSHOT_SAVED(910),
     @UiEvent(doc = "User has discarded the result of a long screenshot")
-    SCREENSHOT_LONG_SCREENSHOT_EXIT(911);
+    SCREENSHOT_LONG_SCREENSHOT_EXIT(911),
+    @UiEvent(doc = "A screenshot has been taken and saved to work profile")
+    SCREENSHOT_SAVED_TO_WORK_PROFILE(1240);
 
     private final int mId;
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
index c41e2bc..4cb91e1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
@@ -15,12 +15,17 @@
  */
 package com.android.systemui.screenshot
 
-import android.app.Service
 import android.content.Intent
 import android.os.IBinder
 import android.util.Log
+import androidx.lifecycle.LifecycleService
+import androidx.lifecycle.lifecycleScope
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.shade.ShadeExpansionStateManager
 import com.android.systemui.statusbar.phone.CentralSurfaces
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 import java.util.Optional
 import javax.inject.Inject
 
@@ -30,7 +35,8 @@
 internal class ScreenshotProxyService @Inject constructor(
     private val mExpansionMgr: ShadeExpansionStateManager,
     private val mCentralSurfacesOptional: Optional<CentralSurfaces>,
-) : Service() {
+    @Main private val mMainDispatcher: CoroutineDispatcher,
+) : LifecycleService() {
 
     private val mBinder: IBinder = object : IScreenshotProxy.Stub() {
         /**
@@ -43,20 +49,28 @@
         }
 
         override fun dismissKeyguard(callback: IOnDoneCallback) {
-            if (mCentralSurfacesOptional.isPresent) {
-                mCentralSurfacesOptional.get().executeRunnableDismissingKeyguard(
-                    Runnable {
-                        callback.onDone(true)
-                    }, null,
-                    true /* dismissShade */, true /* afterKeyguardGone */,
-                    true /* deferred */
-                )
-            } else {
-                callback.onDone(false)
+            lifecycleScope.launch {
+                executeAfterDismissing(callback)
             }
         }
     }
 
+    private suspend fun executeAfterDismissing(callback: IOnDoneCallback) =
+        withContext(mMainDispatcher) {
+            mCentralSurfacesOptional.ifPresentOrElse(
+                    {
+                        it.executeRunnableDismissingKeyguard(
+                                Runnable {
+                                    callback.onDone(true)
+                                }, null,
+                                true /* dismissShade */, true /* afterKeyguardGone */,
+                                true /* deferred */
+                        )
+                    },
+                    { callback.onDone(false) }
+            )
+        }
+
     override fun onBind(intent: Intent): IBinder? {
         Log.d(TAG, "onBind: $intent")
         return mBinder
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java
deleted file mode 100644
index dea8c32..0000000
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.settings;
-
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.systemui.broadcast.BroadcastDispatcher;
-
-/**
- * A class that has an observable for the current user.
- */
-public class CurrentUserObservable {
-
-    private final CurrentUserTracker mTracker;
-
-    private final MutableLiveData<Integer> mCurrentUser = new MutableLiveData<Integer>() {
-        @Override
-        protected void onActive() {
-            super.onActive();
-            mTracker.startTracking();
-        }
-
-        @Override
-        protected void onInactive() {
-            super.onInactive();
-            mTracker.stopTracking();
-        }
-    };
-
-    public CurrentUserObservable(BroadcastDispatcher broadcastDispatcher) {
-        mTracker = new CurrentUserTracker(broadcastDispatcher) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                mCurrentUser.setValue(newUserId);
-            }
-        };
-    }
-
-    /**
-     * Returns the current user that can be observed.
-     */
-    public LiveData<Integer> getCurrentUser() {
-        if (mCurrentUser.getValue() == null) {
-            mCurrentUser.setValue(mTracker.getCurrentUserId());
-        }
-        return mCurrentUser;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
deleted file mode 100644
index 9599d77..0000000
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.settings;
-
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.UserHandle;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public abstract class CurrentUserTracker {
-    private final UserReceiver mUserReceiver;
-
-    private Consumer<Integer> mCallback = this::onUserSwitched;
-
-    public CurrentUserTracker(BroadcastDispatcher broadcastDispatcher) {
-        this(UserReceiver.getInstance(broadcastDispatcher));
-    }
-
-    @VisibleForTesting
-    CurrentUserTracker(UserReceiver receiver) {
-        mUserReceiver = receiver;
-    }
-
-    public int getCurrentUserId() {
-        return mUserReceiver.getCurrentUserId();
-    }
-
-    public void startTracking() {
-        mUserReceiver.addTracker(mCallback);
-    }
-
-    public void stopTracking() {
-        mUserReceiver.removeTracker(mCallback);
-    }
-
-    public abstract void onUserSwitched(int newUserId);
-
-    @VisibleForTesting
-    static class UserReceiver extends BroadcastReceiver {
-        private static UserReceiver sInstance;
-
-        private boolean mReceiverRegistered;
-        private int mCurrentUserId;
-        private final BroadcastDispatcher mBroadcastDispatcher;
-
-        private List<Consumer<Integer>> mCallbacks = new ArrayList<>();
-
-        @VisibleForTesting
-        UserReceiver(BroadcastDispatcher broadcastDispatcher) {
-            mBroadcastDispatcher = broadcastDispatcher;
-        }
-
-        static UserReceiver getInstance(BroadcastDispatcher broadcastDispatcher) {
-            if (sInstance == null) {
-                sInstance = new UserReceiver(broadcastDispatcher);
-            }
-            return sInstance;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-                notifyUserSwitched(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
-            }
-        }
-
-        public int getCurrentUserId() {
-            return mCurrentUserId;
-        }
-
-        private void addTracker(Consumer<Integer> callback) {
-            if (!mCallbacks.contains(callback)) {
-                mCallbacks.add(callback);
-            }
-            if (!mReceiverRegistered) {
-                mCurrentUserId = ActivityManager.getCurrentUser();
-                IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
-                mBroadcastDispatcher.registerReceiver(this, filter, null,
-                        UserHandle.ALL);
-                mReceiverRegistered = true;
-            }
-        }
-
-        private void removeTracker(Consumer<Integer> callback) {
-            if (mCallbacks.contains(callback)) {
-                mCallbacks.remove(callback);
-                if (mCallbacks.size() == 0 && mReceiverRegistered) {
-                    mBroadcastDispatcher.unregisterReceiver(this);
-                    mReceiverRegistered = false;
-                }
-            }
-        }
-
-        private void notifyUserSwitched(int newUserId) {
-            if (mCurrentUserId != newUserId) {
-                mCurrentUserId = newUserId;
-                List<Consumer<Integer>> callbacks = new ArrayList<>(mCallbacks);
-                for (Consumer<Integer> consumer : callbacks) {
-                    // Accepting may modify this list
-                    if (mCallbacks.contains(consumer)) {
-                        consumer.accept(newUserId);
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 7801c68..5880003 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -21,6 +21,7 @@
 import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat;
 
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -46,11 +47,13 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 
+import java.util.concurrent.Executor;
+
 import javax.inject.Inject;
 
 public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
@@ -74,9 +77,10 @@
     private final Context mContext;
     private final ToggleSlider mControl;
     private final DisplayManager mDisplayManager;
-    private final CurrentUserTracker mUserTracker;
+    private final UserTracker mUserTracker;
     private final IVrManager mVrManager;
 
+    private final Executor mMainExecutor;
     private final Handler mBackgroundHandler;
     private final BrightnessObserver mBrightnessObserver;
 
@@ -169,7 +173,7 @@
             }
 
             mBrightnessObserver.startObserving();
-            mUserTracker.startTracking();
+            mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
 
             // Update the slider and mode before attaching the listener so we don't
             // receive the onChanged notifications for the initial values.
@@ -197,7 +201,7 @@
             }
 
             mBrightnessObserver.stopObserving();
-            mUserTracker.stopTracking();
+            mUserTracker.removeCallback(mUserChangedCallback);
 
             mHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
         }
@@ -275,22 +279,27 @@
         }
     };
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    mBackgroundHandler.post(mUpdateModeRunnable);
+                    mBackgroundHandler.post(mUpdateSliderRunnable);
+                }
+            };
+
     public BrightnessController(
             Context context,
             ToggleSlider control,
-            BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
+            @Main Executor mainExecutor,
             @Background Handler bgHandler) {
         mContext = context;
         mControl = control;
         mControl.setMax(GAMMA_SPACE_MAX);
+        mMainExecutor = mainExecutor;
         mBackgroundHandler = bgHandler;
-        mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                mBackgroundHandler.post(mUpdateModeRunnable);
-                mBackgroundHandler.post(mUpdateSliderRunnable);
-            }
-        };
+        mUserTracker = userTracker;
         mBrightnessObserver = new BrightnessObserver(mHandler);
 
         mDisplayId = mContext.getDisplayId();
@@ -364,7 +373,7 @@
                 mControl.setEnforcedAdmin(
                         RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
                                 UserManager.DISALLOW_CONFIG_BRIGHTNESS,
-                                mUserTracker.getCurrentUserId()));
+                                mUserTracker.getUserId()));
             }
         });
     }
@@ -440,16 +449,19 @@
     /** Factory for creating a {@link BrightnessController}. */
     public static class Factory {
         private final Context mContext;
-        private final BroadcastDispatcher mBroadcastDispatcher;
+        private final UserTracker mUserTracker;
+        private final Executor mMainExecutor;
         private final Handler mBackgroundHandler;
 
         @Inject
         public Factory(
                 Context context,
-                BroadcastDispatcher broadcastDispatcher,
+                UserTracker userTracker,
+                @Main Executor mainExecutor,
                 @Background Handler bgHandler) {
             mContext = context;
-            mBroadcastDispatcher = broadcastDispatcher;
+            mUserTracker = userTracker;
+            mMainExecutor = mainExecutor;
             mBackgroundHandler = bgHandler;
         }
 
@@ -458,7 +470,8 @@
             return new BrightnessController(
                     mContext,
                     toggleSlider,
-                    mBroadcastDispatcher,
+                    mUserTracker,
+                    mMainExecutor,
                     mBackgroundHandler);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index d5a3954..e208be9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -34,10 +34,12 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -46,16 +48,19 @@
 
     private BrightnessController mBrightnessController;
     private final BrightnessSliderController.Factory mToggleSliderFactory;
-    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final UserTracker mUserTracker;
+    private final Executor mMainExecutor;
     private final Handler mBackgroundHandler;
 
     @Inject
     public BrightnessDialog(
-            BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
             BrightnessSliderController.Factory factory,
+            @Main Executor mainExecutor,
             @Background Handler bgHandler) {
-        mBroadcastDispatcher = broadcastDispatcher;
+        mUserTracker = userTracker;
         mToggleSliderFactory = factory;
+        mMainExecutor = mainExecutor;
         mBackgroundHandler = bgHandler;
     }
 
@@ -101,7 +106,7 @@
         frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
 
         mBrightnessController = new BrightnessController(
-                this, controller, mBroadcastDispatcher, mBackgroundHandler);
+                this, controller, mUserTracker, mMainExecutor, mBackgroundHandler);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CameraLauncher.java b/packages/SystemUI/src/com/android/systemui/shade/CameraLauncher.java
new file mode 100644
index 0000000..fc61e90
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/CameraLauncher.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade;
+
+import com.android.systemui.camera.CameraGestureHelper;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+
+import javax.inject.Inject;
+
+/** Handles launching camera from Shade. */
+@SysUISingleton
+public class CameraLauncher {
+    private final CameraGestureHelper mCameraGestureHelper;
+    private final KeyguardBypassController mKeyguardBypassController;
+
+    private boolean mLaunchingAffordance;
+
+    @Inject
+    public CameraLauncher(
+            CameraGestureHelper cameraGestureHelper,
+            KeyguardBypassController keyguardBypassController
+    ) {
+        mCameraGestureHelper = cameraGestureHelper;
+        mKeyguardBypassController = keyguardBypassController;
+    }
+
+    /** Launches the camera. */
+    public void launchCamera(int source, boolean isShadeFullyCollapsed) {
+        if (!isShadeFullyCollapsed) {
+            setLaunchingAffordance(true);
+        }
+
+        mCameraGestureHelper.launchCamera(source);
+    }
+
+    /**
+     * Set whether we are currently launching an affordance. This is currently only set when
+     * launched via a camera gesture.
+     */
+    public void setLaunchingAffordance(boolean launchingAffordance) {
+        mLaunchingAffordance = launchingAffordance;
+        mKeyguardBypassController.setLaunchingAffordance(launchingAffordance);
+    }
+
+    /**
+     * Return true when a bottom affordance is launching an occluded activity with a splash screen.
+     */
+    public boolean isLaunchingAffordance() {
+        return mLaunchingAffordance;
+    }
+
+    /**
+     * Whether the camera application can be launched for the camera launch gesture.
+     */
+    public boolean canCameraGestureBeLaunched(int barState) {
+        return mCameraGestureHelper.canCameraGestureBeLaunched(barState);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
index 4063af3..5011227 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
@@ -51,6 +51,8 @@
                 connect(R.id.statusIcons, ConstraintSet.START, R.id.date, ConstraintSet.END)
                 connect(R.id.privacy_container, ConstraintSet.START, R.id.date, ConstraintSet.END)
                 constrainWidth(R.id.statusIcons, ViewGroup.LayoutParams.WRAP_CONTENT)
+                constrainedWidth(R.id.date, true)
+                constrainedWidth(R.id.statusIcons, true)
             }
         )
     }
@@ -92,7 +94,8 @@
                     centerEnd,
                     ConstraintSet.END
                 )
-                constrainWidth(R.id.statusIcons, 0)
+                constrainedWidth(R.id.date, true)
+                constrainedWidth(R.id.statusIcons, true)
             },
             qsConstraintsChanges = {
                 setGuidelineBegin(centerStart, offsetFromEdge)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index cfc1178..92dc459 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -124,7 +124,6 @@
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.animation.LaunchAnimator;
 import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.camera.CameraGestureHelper;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dagger.qualifiers.DisplayId;
@@ -178,6 +177,7 @@
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -254,6 +254,8 @@
     private static final int FLING_COLLAPSE = 1;
     /** Fling until QS is completely hidden. */
     private static final int FLING_HIDE = 2;
+    /** The delay to reset the hint text when the hint animation is finished running. */
+    private static final int HINT_RESET_DELAY_MS = 1200;
     private static final long ANIMATION_DELAY_ICON_FADE_IN =
             ActivityLaunchAnimator.TIMINGS.getTotalDuration()
                     - CollapsedStatusBarFragment.FADE_IN_DURATION
@@ -344,6 +346,7 @@
     private final FalsingTapListener mFalsingTapListener = this::falsingAdditionalTapRequired;
     private final FragmentListener mQsFragmentListener = new QsFragmentListener();
     private final AccessibilityDelegate mAccessibilityDelegate = new ShadeAccessibilityDelegate();
+    private final NotificationGutsManager mGutsManager;
 
     private long mDownTime;
     private boolean mTouchSlopExceededBeforeDown;
@@ -464,7 +467,6 @@
     private boolean mCollapsedOnDown;
     private boolean mClosingWithAlphaFadeOut;
     private boolean mHeadsUpAnimatingAway;
-    private boolean mLaunchingAffordance;
     private final FalsingManager mFalsingManager;
     private final FalsingCollector mFalsingCollector;
 
@@ -575,7 +577,7 @@
 
     /** Whether the current animator is resetting the pulse expansion after a drag down. */
     private boolean mIsPulseExpansionResetAnimator;
-    private final Rect mKeyguardStatusAreaClipBounds = new Rect();
+    private final Rect mLastQsClipBounds = new Rect();
     private final Region mQsInterceptRegion = new Region();
     /** Alpha of the views which only show on the keyguard but not in shade / shade locked. */
     private float mKeyguardOnlyContentAlpha = 1.0f;
@@ -615,7 +617,6 @@
     private final NotificationListContainer mNotificationListContainer;
     private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
     private final NPVCDownEventState.Buffer mLastDownEvents;
-    private final CameraGestureHelper mCameraGestureHelper;
     private final KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
     private final KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
     private float mMinExpandHeight;
@@ -628,7 +629,6 @@
     private float mLastGesturedOverExpansion = -1;
     /** Whether the current animator is the spring back animation. */
     private boolean mIsSpringBackAnimation;
-    private boolean mInSplitShade;
     private float mHintDistance;
     private float mInitialOffsetOnTouch;
     private boolean mCollapsedAndHeadsUpOnDown;
@@ -705,6 +705,7 @@
             ConversationNotificationManager conversationNotificationManager,
             MediaHierarchyManager mediaHierarchyManager,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            NotificationGutsManager gutsManager,
             NotificationsQSContainerController notificationsQSContainerController,
             NotificationStackScrollLayoutController notificationStackScrollLayoutController,
             KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
@@ -743,7 +744,6 @@
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             ShadeTransitionController shadeTransitionController,
             SystemClock systemClock,
-            CameraGestureHelper cameraGestureHelper,
             KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
             KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
             DumpManager dumpManager) {
@@ -759,6 +759,7 @@
         mLockscreenGestureLogger = lockscreenGestureLogger;
         mShadeExpansionStateManager = shadeExpansionStateManager;
         mShadeLog = shadeLogger;
+        mGutsManager = gutsManager;
         mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
             @Override
             public void onViewAttachedToWindow(View v) {
@@ -924,7 +925,6 @@
                         unlockAnimationStarted(playingCannedAnimation, isWakeAndUnlock, startDelay);
                     }
                 });
-        mCameraGestureHelper = cameraGestureHelper;
         mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
         dumpManager.registerDumpable(this);
     }
@@ -1066,7 +1066,6 @@
         mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
         mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
         mPanelFlingOvershootAmount = mResources.getDimension(R.dimen.panel_overshoot_amount);
-        mInSplitShade = mResources.getBoolean(R.bool.config_use_split_notification_shade);
         mFlingAnimationUtils = mFlingAnimationUtilsBuilder.get()
                 .setMaxLengthSeconds(0.4f).build();
         mStatusBarMinHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
@@ -1574,23 +1573,31 @@
                     // Find the clock, so we can exclude it from this transition.
                     FrameLayout clockContainerView =
                             mView.findViewById(R.id.lockscreen_clock_view_large);
-                    View clockView = clockContainerView.getChildAt(0);
 
-                    transition.excludeTarget(clockView, /* exclude= */ true);
+                    // The clock container can sometimes be null. If it is, just fall back to the
+                    // old animation rather than setting up the custom animations.
+                    if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+                        TransitionManager.beginDelayedTransition(
+                                mNotificationContainerParent, transition);
+                    } else {
+                        View clockView = clockContainerView.getChildAt(0);
 
-                    TransitionSet set = new TransitionSet();
-                    set.addTransition(transition);
+                        transition.excludeTarget(clockView, /* exclude= */ true);
 
-                    SplitShadeTransitionAdapter adapter =
-                            new SplitShadeTransitionAdapter(mKeyguardStatusViewController);
+                        TransitionSet set = new TransitionSet();
+                        set.addTransition(transition);
 
-                    // Use linear here, so the actual clock can pick its own interpolator.
-                    adapter.setInterpolator(Interpolators.LINEAR);
-                    adapter.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                    adapter.addTarget(clockView);
-                    set.addTransition(adapter);
+                        SplitShadeTransitionAdapter adapter =
+                                new SplitShadeTransitionAdapter(mKeyguardStatusViewController);
 
-                    TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
+                        // Use linear here, so the actual clock can pick its own interpolator.
+                        adapter.setInterpolator(Interpolators.LINEAR);
+                        adapter.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                        adapter.addTarget(clockView);
+                        set.addTransition(adapter);
+
+                        TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
+                    }
                 } else {
                     TransitionManager.beginDelayedTransition(
                             mNotificationContainerParent, transition);
@@ -1765,7 +1772,7 @@
     }
 
     public void resetViews(boolean animate) {
-        mCentralSurfaces.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */,
+        mGutsManager.closeAndSaveGuts(true /* leavebehind */, true /* force */,
                 true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
         if (animate && !isFullyCollapsed()) {
             animateCloseQs(true /* animateAway */);
@@ -1841,6 +1848,10 @@
     public void closeQs() {
         cancelQsAnimation();
         setQsExpansionHeight(mQsMinExpansionHeight);
+        // qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
+        // middle of animation - we need to make sure that value is always false when shade if
+        // fully collapsed or expanded
+        setQsExpandImmediate(false);
     }
 
     @VisibleForTesting
@@ -1943,7 +1954,7 @@
         // we want to perform an overshoot animation when flinging open
         final boolean addOverscroll =
                 expand
-                        && !mInSplitShade // Split shade has its own overscroll logic
+                        && !mSplitShadeEnabled // Split shade has its own overscroll logic
                         && mStatusBarStateController.getState() != KEYGUARD
                         && mOverExpansion == 0.0f
                         && vel >= 0;
@@ -2732,8 +2743,10 @@
      * as well based on the bounds of the shade and QS state.
      */
     private void setQSClippingBounds() {
-        final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
-        final boolean qsVisible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0);
+        float qsExpansionFraction = computeQsExpansionFraction();
+        final int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
+        final boolean qsVisible = (qsExpansionFraction > 0 || qsPanelBottomY > 0);
+        checkCorrectScrimVisibility(qsExpansionFraction);
 
         int top = calculateTopQsClippingBound(qsPanelBottomY);
         int bottom = calculateBottomQsClippingBound(top);
@@ -2744,6 +2757,19 @@
         applyQSClippingBounds(left, top, right, bottom, qsVisible);
     }
 
+    private void checkCorrectScrimVisibility(float expansionFraction) {
+        // issues with scrims visible on keyguard occur only in split shade
+        if (mSplitShadeEnabled) {
+            boolean keyguardViewsVisible = mBarState == KEYGUARD && mKeyguardOnlyContentAlpha == 1;
+            // expansionFraction == 1 means scrims are fully visible as their size/visibility depend
+            // on QS expansion
+            if (expansionFraction == 1 && keyguardViewsVisible) {
+                Log.wtf(TAG,
+                        "Incorrect state, scrim is visible at the same time when clock is visible");
+            }
+        }
+    }
+
     private int calculateTopQsClippingBound(int qsPanelBottomY) {
         int top;
         if (mSplitShadeEnabled) {
@@ -2814,7 +2840,7 @@
      */
     private void applyQSClippingBounds(int left, int top, int right, int bottom,
             boolean qsVisible) {
-        if (!mAnimateNextNotificationBounds || mKeyguardStatusAreaClipBounds.isEmpty()) {
+        if (!mAnimateNextNotificationBounds || mLastQsClipBounds.isEmpty()) {
             if (mQsClippingAnimation != null) {
                 // update the end position of the animator
                 mQsClippingAnimationEndBounds.set(left, top, right, bottom);
@@ -2823,10 +2849,10 @@
             }
         } else {
             mQsClippingAnimationEndBounds.set(left, top, right, bottom);
-            final int startLeft = mKeyguardStatusAreaClipBounds.left;
-            final int startTop = mKeyguardStatusAreaClipBounds.top;
-            final int startRight = mKeyguardStatusAreaClipBounds.right;
-            final int startBottom = mKeyguardStatusAreaClipBounds.bottom;
+            final int startLeft = mLastQsClipBounds.left;
+            final int startTop = mLastQsClipBounds.top;
+            final int startRight = mLastQsClipBounds.right;
+            final int startBottom = mLastQsClipBounds.bottom;
             if (mQsClippingAnimation != null) {
                 mQsClippingAnimation.cancel();
             }
@@ -2863,12 +2889,10 @@
 
     private void applyQSClippingImmediately(int left, int top, int right, int bottom,
             boolean qsVisible) {
-        // Fancy clipping for quick settings
         int radius = mScrimCornerRadius;
         boolean clipStatusView = false;
+        mLastQsClipBounds.set(left, top, right, bottom);
         if (mIsFullWidth) {
-            // The padding on this area is large enough that we can use a cheaper clipping strategy
-            mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
             clipStatusView = qsVisible;
             float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
             radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
@@ -2903,8 +2927,8 @@
                     radius,
                     qsVisible && !mSplitShadeEnabled);
         }
-        mKeyguardStatusViewController.setClipBounds(
-                clipStatusView ? mKeyguardStatusAreaClipBounds : null);
+        // The padding on this area is large enough that we can use a cheaper clipping strategy
+        mKeyguardStatusViewController.setClipBounds(clipStatusView ? mLastQsClipBounds : null);
         if (!qsVisible && mSplitShadeEnabled) {
             // On the lockscreen when qs isn't visible, we don't want the bounds of the shade to
             // be visible, otherwise you can see the bounds once swiping up to see bouncer
@@ -3693,7 +3717,6 @@
     private void onTrackingStopped(boolean expand) {
         mFalsingCollector.onTrackingStopped();
         mTracking = false;
-        mCentralSurfaces.onTrackingStopped(expand);
         updatePanelExpansionAndVisibility();
         if (expand) {
             mNotificationStackScrollLayoutController.setOverScrollAmount(0.0f, true /* onTop */,
@@ -3736,14 +3759,16 @@
 
     @VisibleForTesting
     void onUnlockHintFinished() {
-        mCentralSurfaces.onHintFinished();
+        // Delay the reset a bit so the user can read the text.
+        mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
         mScrimController.setExpansionAffectsAlpha(true);
         mNotificationStackScrollLayoutController.setUnlockHintRunning(false);
     }
 
     @VisibleForTesting
     void onUnlockHintStarted() {
-        mCentralSurfaces.onUnlockHintStarted();
+        mFalsingCollector.onUnlockHintStarted();
+        mKeyguardIndicationController.showActionToUnlock();
         mScrimController.setExpansionAffectsAlpha(false);
         mNotificationStackScrollLayoutController.setUnlockHintRunning(true);
     }
@@ -3948,6 +3973,10 @@
         }
     }
 
+    public int getBarState() {
+        return mBarState;
+    }
+
     private boolean isOnKeyguard() {
         return mBarState == KEYGUARD;
     }
@@ -3993,35 +4022,6 @@
                 && mBarState == StatusBarState.SHADE;
     }
 
-    /** Launches the camera. */
-    public void launchCamera(int source) {
-        if (!isFullyCollapsed()) {
-            setLaunchingAffordance(true);
-        }
-
-        mCameraGestureHelper.launchCamera(source);
-    }
-
-    public void onAffordanceLaunchEnded() {
-        setLaunchingAffordance(false);
-    }
-
-    /** Set whether we are currently launching an affordance (i.e. camera gesture). */
-    private void setLaunchingAffordance(boolean launchingAffordance) {
-        mLaunchingAffordance = launchingAffordance;
-        mKeyguardBypassController.setLaunchingAffordance(launchingAffordance);
-    }
-
-    /** Returns whether a bottom affordance is launching an occluded activity with splash screen. */
-    public boolean isLaunchingAffordanceWithPreview() {
-        return mLaunchingAffordance;
-    }
-
-    /** Whether the camera application can be launched by the camera launch gesture. */
-    public boolean canCameraGestureBeLaunched() {
-        return mCameraGestureHelper.canCameraGestureBeLaunched(mBarState);
-    }
-
     public boolean hideStatusBarIconsWhenExpanded() {
         if (mIsLaunchAnimationRunning) {
             return mHideIconsDuringLaunchAnimation;
@@ -4360,7 +4360,6 @@
         ipw.print("mCollapsedOnDown="); ipw.println(mCollapsedOnDown);
         ipw.print("mClosingWithAlphaFadeOut="); ipw.println(mClosingWithAlphaFadeOut);
         ipw.print("mHeadsUpAnimatingAway="); ipw.println(mHeadsUpAnimatingAway);
-        ipw.print("mLaunchingAffordance="); ipw.println(mLaunchingAffordance);
         ipw.print("mShowIconsWhenExpanded="); ipw.println(mShowIconsWhenExpanded);
         ipw.print("mIndicationBottomPadding="); ipw.println(mIndicationBottomPadding);
         ipw.print("mAmbientIndicationBottomPadding="); ipw.println(mAmbientIndicationBottomPadding);
@@ -4426,7 +4425,7 @@
         ipw.print("mPanelFlingOvershootAmount="); ipw.println(mPanelFlingOvershootAmount);
         ipw.print("mLastGesturedOverExpansion="); ipw.println(mLastGesturedOverExpansion);
         ipw.print("mIsSpringBackAnimation="); ipw.println(mIsSpringBackAnimation);
-        ipw.print("mInSplitShade="); ipw.println(mInSplitShade);
+        ipw.print("mSplitShadeEnabled="); ipw.println(mSplitShadeEnabled);
         ipw.print("mHintDistance="); ipw.println(mHintDistance);
         ipw.print("mInitialOffsetOnTouch="); ipw.println(mInitialOffsetOnTouch);
         ipw.print("mCollapsedAndHeadsUpOnDown="); ipw.println(mCollapsedAndHeadsUpOnDown);
@@ -4795,7 +4794,6 @@
             }
 
             mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
-                    mCentralSurfaces.isFalsingThresholdNeeded(),
                     mCentralSurfaces.isWakeUpComingFromTouch());
             // Log collapse gesture if on lock screen.
             if (!expand && onKeyguard) {
@@ -4844,9 +4842,6 @@
      */
     private boolean isFalseTouch(float x, float y,
             @Classifier.InteractionType int interactionType) {
-        if (!mCentralSurfaces.isFalsingThresholdNeeded()) {
-            return false;
-        }
         if (mFalsingManager.isClassifierEnabled()) {
             return mFalsingManager.isFalseTouch(interactionType);
         }
@@ -4944,7 +4939,7 @@
             float maxPanelHeight = getMaxPanelTransitionDistance();
             if (mHeightAnimator == null) {
                 // Split shade has its own overscroll logic
-                if (mTracking && !mInSplitShade) {
+                if (mTracking && !mSplitShadeEnabled) {
                     float overExpansionPixels = Math.max(0, h - maxPanelHeight);
                     setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
                 }
@@ -5492,6 +5487,12 @@
                 //  - from SHADE to KEYGUARD
                 //  - from SHADE_LOCKED to SHADE
                 //  - getting notified again about the current SHADE or KEYGUARD state
+                if (mSplitShadeEnabled && oldState == SHADE && statusBarState == KEYGUARD) {
+                    // user can go to keyguard from different shade states and closing animation
+                    // may not fully run - we always want to make sure we close QS when that happens
+                    // as we never need QS open in fresh keyguard state
+                    closeQs();
+                }
                 final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE
                         && statusBarState == KEYGUARD
                         && mScreenOffAnimationController.isKeyguardShowDelayed();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index e52170e..6acf417 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shade;
 
+import static android.os.Trace.TRACE_TAG_ALWAYS;
 import static android.view.WindowInsets.Type.systemBars;
 
 import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
@@ -23,6 +24,7 @@
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.LayoutRes;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -33,7 +35,9 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Trace;
 import android.util.AttributeSet;
+import android.util.Pair;
 import android.view.ActionMode;
 import android.view.DisplayCutout;
 import android.view.InputQueue;
@@ -72,6 +76,7 @@
     private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
 
     private InteractionEventHandler mInteractionEventHandler;
+    private LayoutInsetsController mLayoutInsetProvider;
 
     public NotificationShadeWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -106,12 +111,10 @@
         mLeftInset = 0;
         mRightInset = 0;
         DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
-        if (displayCutout != null) {
-            mLeftInset = displayCutout.getSafeInsetLeft();
-            mRightInset = displayCutout.getSafeInsetRight();
-        }
-        mLeftInset = Math.max(insets.left, mLeftInset);
-        mRightInset = Math.max(insets.right, mRightInset);
+        Pair<Integer, Integer> pairInsets = mLayoutInsetProvider
+                .getinsets(windowInsets, displayCutout);
+        mLeftInset = pairInsets.first;
+        mRightInset = pairInsets.second;
         applyMargins();
         return windowInsets;
     }
@@ -170,6 +173,10 @@
         mInteractionEventHandler = listener;
     }
 
+    protected void setLayoutInsetsController(LayoutInsetsController provider) {
+        mLayoutInsetProvider = provider;
+    }
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);
@@ -299,6 +306,19 @@
         return mode;
     }
 
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        Trace.beginSection("NotificationShadeWindowView#onMeasure");
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        Trace.endSection();
+    }
+
+    @Override
+    public void requestLayout() {
+        Trace.instant(TRACE_TAG_ALWAYS, "NotificationShadeWindowView#requestLayout");
+        super.requestLayout();
+    }
+
     private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
         private final ActionMode.Callback mWrapped;
 
@@ -338,6 +358,18 @@
         }
     }
 
+    /**
+     * Controller responsible for calculating insets for the shade window.
+     */
+    public interface LayoutInsetsController {
+
+        /**
+         * Update the insets and calculate them accordingly.
+         */
+        Pair<Integer, Integer> getinsets(@Nullable WindowInsets windowInsets,
+                @Nullable DisplayCutout displayCutout);
+    }
+
     interface InteractionEventHandler {
         /**
          * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index bb67280c..8379e51 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -42,6 +42,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationInsetsController;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -76,6 +77,7 @@
     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private final AmbientState mAmbientState;
     private final PulsingGestureListener mPulsingGestureListener;
+    private final NotificationInsetsController mNotificationInsetsController;
 
     private GestureDetector mPulsingWakeupGestureHandler;
     private View mBrightnessMirror;
@@ -111,6 +113,7 @@
             CentralSurfaces centralSurfaces,
             NotificationShadeWindowController controller,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+            NotificationInsetsController notificationInsetsController,
             AmbientState ambientState,
             PulsingGestureListener pulsingGestureListener,
             FeatureFlags featureFlags,
@@ -134,6 +137,7 @@
         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
         mAmbientState = ambientState;
         mPulsingGestureListener = pulsingGestureListener;
+        mNotificationInsetsController = notificationInsetsController;
 
         // This view is not part of the newly inflated expanded status bar.
         mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -165,6 +169,7 @@
         mPulsingWakeupGestureHandler = new GestureDetector(mView.getContext(),
                 mPulsingGestureListener);
 
+        mView.setLayoutInsetsController(mNotificationInsetsController);
         mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {
             @Override
             public Boolean handleDispatchTouchEvent(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 3670d09..0f27420 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -36,7 +36,7 @@
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO;
-import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_RESTING;
+import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
@@ -55,7 +55,6 @@
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.BatteryManager;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -64,11 +63,11 @@
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.text.format.Formatter;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -76,6 +75,8 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.TrustGrantFlags;
+import com.android.keyguard.logging.KeyguardLogger;
 import com.android.settingslib.Utils;
 import com.android.settingslib.fuelgauge.BatteryStatus;
 import com.android.systemui.R;
@@ -123,7 +124,6 @@
 
     private static final String TAG = "KeyguardIndication";
     private static final boolean DEBUG_CHARGING_SPEED = false;
-    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
 
     private static final int MSG_HIDE_TRANSIENT = 1;
     private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2;
@@ -139,6 +139,7 @@
     protected final StatusBarStateController mStatusBarStateController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final AuthController mAuthController;
+    private final KeyguardLogger mKeyguardLogger;
     private ViewGroup mIndicationArea;
     private KeyguardIndicationTextView mTopIndicationView;
     private KeyguardIndicationTextView mLockScreenIndicationView;
@@ -155,11 +156,12 @@
     private final AccessibilityManager mAccessibilityManager;
     private final Handler mHandler;
 
-    protected KeyguardIndicationRotateTextViewController mRotateTextViewController;
+    @VisibleForTesting
+    public KeyguardIndicationRotateTextViewController mRotateTextViewController;
     private BroadcastReceiver mBroadcastReceiver;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
-    private String mRestingIndication;
+    private String mPersistentUnlockMessage;
     private String mAlignmentIndication;
     private CharSequence mTrustGrantedIndication;
     private CharSequence mTransientIndication;
@@ -196,7 +198,9 @@
         public void onScreenTurnedOn() {
             mHandler.removeMessages(MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON);
             if (mBiometricErrorMessageToShowOnScreenOn != null) {
-                showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn);
+                String followUpMessage = mFaceLockedOutThisAuthSession
+                        ? faceLockedOutFollowupMessage() : null;
+                showBiometricMessage(mBiometricErrorMessageToShowOnScreenOn, followUpMessage);
                 // We want to keep this message around in case the screen was off
                 hideBiometricMessageDelayed(DEFAULT_HIDE_DELAY_MS);
                 mBiometricErrorMessageToShowOnScreenOn = null;
@@ -229,7 +233,8 @@
             ScreenLifecycle screenLifecycle,
             KeyguardBypassController keyguardBypassController,
             AccessibilityManager accessibilityManager,
-            FaceHelpMessageDeferral faceHelpMessageDeferral) {
+            FaceHelpMessageDeferral faceHelpMessageDeferral,
+            KeyguardLogger keyguardLogger) {
         mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
         mDevicePolicyManager = devicePolicyManager;
@@ -249,6 +254,7 @@
         mKeyguardBypassController = keyguardBypassController;
         mAccessibilityManager = accessibilityManager;
         mScreenLifecycle = screenLifecycle;
+        mKeyguardLogger = keyguardLogger;
         mScreenLifecycle.addObserver(mScreenObserver);
 
         mFaceAcquiredMessageDeferral = faceHelpMessageDeferral;
@@ -373,7 +379,7 @@
         updateLockScreenTrustMsg(userId, getTrustGrantedIndication(), getTrustManagedIndication());
         updateLockScreenAlignmentMsg();
         updateLockScreenLogoutView();
-        updateLockScreenRestingMsg();
+        updateLockScreenPersistentUnlockMsg();
     }
 
     private void updateOrganizedOwnedDevice() {
@@ -479,7 +485,8 @@
     }
 
     private void updateLockScreenUserLockedMsg(int userId) {
-        if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
+        if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)
+                || mKeyguardUpdateMonitor.isEncryptedOrLockdown(userId)) {
             mRotateTextViewController.updateIndication(
                     INDICATION_TYPE_USER_LOCKED,
                     new KeyguardIndication.Builder()
@@ -584,18 +591,17 @@
         }
     }
 
-    private void updateLockScreenRestingMsg() {
-        if (!TextUtils.isEmpty(mRestingIndication)
-                && !mRotateTextViewController.hasIndications()) {
+    private void updateLockScreenPersistentUnlockMsg() {
+        if (!TextUtils.isEmpty(mPersistentUnlockMessage)) {
             mRotateTextViewController.updateIndication(
-                    INDICATION_TYPE_RESTING,
+                    INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE,
                     new KeyguardIndication.Builder()
-                            .setMessage(mRestingIndication)
+                            .setMessage(mPersistentUnlockMessage)
                             .setTextColor(mInitialTextColorState)
                             .build(),
-                    false);
+                    true);
         } else {
-            mRotateTextViewController.hideIndication(INDICATION_TYPE_RESTING);
+            mRotateTextViewController.hideIndication(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE);
         }
     }
 
@@ -678,11 +684,8 @@
         }
     }
 
-    /**
-     * Sets the indication that is shown if nothing else is showing.
-     */
-    public void setRestingIndication(String restingIndication) {
-        mRestingIndication = restingIndication;
+    private void setPersistentUnlockMessage(String persistentUnlockMessage) {
+        mPersistentUnlockMessage = persistentUnlockMessage;
         updateDeviceEntryIndication(false);
     }
 
@@ -1024,7 +1027,7 @@
                 mChargingTimeRemaining = mPowerPluggedIn
                         ? mBatteryInfo.computeChargeTimeRemaining() : -1;
             } catch (RemoteException e) {
-                Log.e(TAG, "Error calling IBatteryStats: ", e);
+                mKeyguardLogger.logException(e, "Error calling IBatteryStats");
                 mChargingTimeRemaining = -1;
             }
             updateDeviceEntryIndication(!wasPluggedIn && mPowerPluggedInWired);
@@ -1072,8 +1075,10 @@
             final boolean isCoExFaceAcquisitionMessage =
                     faceAuthSoftError && isUnlockWithFingerprintPossible;
             if (isCoExFaceAcquisitionMessage && !mCoExFaceAcquisitionMsgIdsToShow.contains(msgId)) {
-                debugLog("skip showing msgId=" + msgId + " helpString=" + helpString
-                        + ", due to co-ex logic");
+                mKeyguardLogger.logBiometricMessage(
+                        "skipped showing help message due to co-ex logic",
+                        msgId,
+                        helpString);
             } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mStatusBarKeyguardViewManager.setKeyguardMessage(helpString,
                         mInitialTextColorState);
@@ -1114,6 +1119,9 @@
         public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) {
             if (biometricSourceType == FACE && !mKeyguardUpdateMonitor.isFaceLockedOut()) {
                 mFaceLockedOutThisAuthSession = false;
+            } else if (biometricSourceType == FINGERPRINT) {
+                setPersistentUnlockMessage(mKeyguardUpdateMonitor.isFingerprintLockedOut()
+                        ? mContext.getString(R.string.keyguard_unlock) : "");
             }
         }
 
@@ -1131,7 +1139,7 @@
             CharSequence deferredFaceMessage = mFaceAcquiredMessageDeferral.getDeferredMessage();
             mFaceAcquiredMessageDeferral.reset();
             if (shouldSuppressFaceError(msgId, mKeyguardUpdateMonitor)) {
-                debugLog("suppressingFaceError msgId=" + msgId + " errString= " + errString);
+                mKeyguardLogger.logBiometricMessage("suppressingFaceError", msgId, errString);
                 return;
             }
             if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
@@ -1145,8 +1153,9 @@
 
         private void onFingerprintAuthError(int msgId, String errString) {
             if (shouldSuppressFingerprintError(msgId, mKeyguardUpdateMonitor)) {
-                debugLog("suppressingFingerprintError msgId=" + msgId
-                        + " errString= " + errString);
+                mKeyguardLogger.logBiometricMessage("suppressingFingerprintError",
+                        msgId,
+                        errString);
             } else {
                 showErrorMessageNowOrLater(errString, null);
             }
@@ -1179,16 +1188,14 @@
 
         @Override
         public void onTrustChanged(int userId) {
-            if (getCurrentUser() != userId) {
-                return;
-            }
+            if (!isCurrentUser(userId)) return;
             updateDeviceEntryIndication(false);
         }
 
         @Override
-        public void showTrustGrantedMessage(CharSequence message) {
-            mTrustGrantedIndication = message;
-            updateDeviceEntryIndication(false);
+        public void onTrustGrantedForCurrentUser(boolean dismissKeyguard,
+                @NonNull TrustGrantFlags flags, @Nullable String message) {
+            showTrustGrantedMessage(dismissKeyguard, message);
         }
 
         @Override
@@ -1248,10 +1255,17 @@
         }
     }
 
+    private boolean isCurrentUser(int userId) {
+        return getCurrentUser() == userId;
+    }
+
+    protected void showTrustGrantedMessage(boolean dismissKeyguard, @Nullable String message) {
+        mTrustGrantedIndication = message;
+        updateDeviceEntryIndication(false);
+    }
+
     private void handleFaceLockoutError(String errString) {
-        int followupMsgId = canUnlockWithFingerprint() ? R.string.keyguard_suggest_fingerprint
-                : R.string.keyguard_unlock;
-        String followupMessage = mContext.getString(followupMsgId);
+        String followupMessage = faceLockedOutFollowupMessage();
         // Lockout error can happen multiple times in a session because we trigger face auth
         // even when it is locked out so that the user is aware that face unlock would have
         // triggered but didn't because it is locked out.
@@ -1263,18 +1277,26 @@
             showErrorMessageNowOrLater(errString, followupMessage);
         } else if (!mAuthController.isUdfpsFingerDown()) {
             // On subsequent lockouts, we show a more generic locked out message.
-            showBiometricMessage(mContext.getString(R.string.keyguard_face_unlock_unavailable),
+            showErrorMessageNowOrLater(
+                    mContext.getString(R.string.keyguard_face_unlock_unavailable),
                     followupMessage);
         }
     }
 
+    private String faceLockedOutFollowupMessage() {
+        int followupMsgId = canUnlockWithFingerprint() ? R.string.keyguard_suggest_fingerprint
+                : R.string.keyguard_unlock;
+        return mContext.getString(followupMsgId);
+    }
+
     private static boolean isLockoutError(int msgId) {
         return msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT
                 || msgId == FaceManager.FACE_ERROR_LOCKOUT;
     }
 
     private void handleFaceAuthTimeoutError(@Nullable CharSequence deferredFaceMessage) {
-        debugLog("showDeferredFaceMessage msgId=" + deferredFaceMessage);
+        mKeyguardLogger.logBiometricMessage("deferred message after face auth timeout",
+                null, String.valueOf(deferredFaceMessage));
         if (canUnlockWithFingerprint()) {
             // Co-ex: show deferred message OR nothing
             // if we're on the lock screen (bouncer isn't showing), show the deferred msg
@@ -1286,7 +1308,8 @@
                 );
             } else {
                 // otherwise, don't show any message
-                debugLog("skip showing FACE_ERROR_TIMEOUT due to co-ex logic");
+                mKeyguardLogger.logBiometricMessage(
+                        "skip showing FACE_ERROR_TIMEOUT due to co-ex logic");
             }
         } else if (deferredFaceMessage != null) {
             // Face-only: The face timeout message is not very actionable, let's ask the
@@ -1307,12 +1330,6 @@
                 KeyguardUpdateMonitor.getCurrentUser());
     }
 
-    private void debugLog(String logMsg) {
-        if (DEBUG) {
-            Log.d(TAG, logMsg);
-        }
-    }
-
     private void showErrorMessageNowOrLater(String errString, @Nullable String followUpMsg) {
         if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
             mStatusBarKeyguardViewManager.setKeyguardMessage(errString, mInitialTextColorState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 9d2750f..bc456d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -18,6 +18,8 @@
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.statusbar.LightRevealEffect.Companion.getPercentPastThreshold
 import com.android.systemui.util.getColorWithAlpha
+import com.android.systemui.util.leak.RotationUtils
+import com.android.systemui.util.leak.RotationUtils.Rotation
 import java.util.function.Consumer
 
 /**
@@ -67,22 +69,19 @@
     override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
         val interpolatedAmount = INTERPOLATOR.getInterpolation(amount)
         val ovalWidthIncreaseAmount =
-                getPercentPastThreshold(interpolatedAmount, WIDEN_OVAL_THRESHOLD)
+            getPercentPastThreshold(interpolatedAmount, WIDEN_OVAL_THRESHOLD)
 
         val initialWidthMultiplier = (1f - OVAL_INITIAL_WIDTH_PERCENT) / 2f
 
         with(scrim) {
-            revealGradientEndColorAlpha = 1f - getPercentPastThreshold(
-                    amount, FADE_END_COLOR_OUT_THRESHOLD)
+            revealGradientEndColorAlpha =
+                1f - getPercentPastThreshold(amount, FADE_END_COLOR_OUT_THRESHOLD)
             setRevealGradientBounds(
-                    scrim.width * initialWidthMultiplier +
-                            -scrim.width * ovalWidthIncreaseAmount,
-                    scrim.height * OVAL_INITIAL_TOP_PERCENT -
-                            scrim.height * interpolatedAmount,
-                    scrim.width * (1f - initialWidthMultiplier) +
-                            scrim.width * ovalWidthIncreaseAmount,
-                    scrim.height * OVAL_INITIAL_BOTTOM_PERCENT +
-                            scrim.height * interpolatedAmount)
+                scrim.width * initialWidthMultiplier + -scrim.width * ovalWidthIncreaseAmount,
+                scrim.height * OVAL_INITIAL_TOP_PERCENT - scrim.height * interpolatedAmount,
+                scrim.width * (1f - initialWidthMultiplier) + scrim.width * ovalWidthIncreaseAmount,
+                scrim.height * OVAL_INITIAL_BOTTOM_PERCENT + scrim.height * interpolatedAmount
+            )
         }
     }
 }
@@ -97,12 +96,17 @@
         scrim.interpolatedRevealAmount = interpolatedAmount
 
         scrim.startColorAlpha =
-            getPercentPastThreshold(1 - interpolatedAmount,
-                threshold = 1 - START_COLOR_REVEAL_PERCENTAGE)
+            getPercentPastThreshold(
+                1 - interpolatedAmount,
+                threshold = 1 - START_COLOR_REVEAL_PERCENTAGE
+            )
 
         scrim.revealGradientEndColorAlpha =
-            1f - getPercentPastThreshold(interpolatedAmount,
-                threshold = REVEAL_GRADIENT_END_COLOR_ALPHA_START_PERCENTAGE)
+            1f -
+                getPercentPastThreshold(
+                    interpolatedAmount,
+                    threshold = REVEAL_GRADIENT_END_COLOR_ALPHA_START_PERCENTAGE
+                )
 
         // Start changing gradient bounds later to avoid harsh gradient in the beginning
         val gradientBoundsAmount = lerp(GRADIENT_START_BOUNDS_PERCENTAGE, 1.0f, interpolatedAmount)
@@ -179,7 +183,7 @@
      */
     private val OFF_SCREEN_START_AMOUNT = 0.05f
 
-    private val WIDTH_INCREASE_MULTIPLIER = 1.25f
+    private val INCREASE_MULTIPLIER = 1.25f
 
     override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
         val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN_REVERSE.getInterpolation(amount)
@@ -188,15 +192,36 @@
         with(scrim) {
             revealGradientEndColorAlpha = 1f - fadeAmount
             interpolatedRevealAmount = interpolatedAmount
-            setRevealGradientBounds(
+            @Rotation val rotation = RotationUtils.getRotation(scrim.getContext())
+            if (rotation == RotationUtils.ROTATION_NONE) {
+                setRevealGradientBounds(
                     width * (1f + OFF_SCREEN_START_AMOUNT) -
-                            width * WIDTH_INCREASE_MULTIPLIER * interpolatedAmount,
-                    powerButtonY -
-                            height * interpolatedAmount,
+                        width * INCREASE_MULTIPLIER * interpolatedAmount,
+                    powerButtonY - height * interpolatedAmount,
                     width * (1f + OFF_SCREEN_START_AMOUNT) +
-                            width * WIDTH_INCREASE_MULTIPLIER * interpolatedAmount,
-                    powerButtonY +
-                            height * interpolatedAmount)
+                        width * INCREASE_MULTIPLIER * interpolatedAmount,
+                    powerButtonY + height * interpolatedAmount
+                )
+            } else if (rotation == RotationUtils.ROTATION_LANDSCAPE) {
+                setRevealGradientBounds(
+                    powerButtonY - width * interpolatedAmount,
+                    (-height * OFF_SCREEN_START_AMOUNT) -
+                        height * INCREASE_MULTIPLIER * interpolatedAmount,
+                    powerButtonY + width * interpolatedAmount,
+                    (-height * OFF_SCREEN_START_AMOUNT) +
+                        height * INCREASE_MULTIPLIER * interpolatedAmount
+                )
+            } else {
+                // RotationUtils.ROTATION_SEASCAPE
+                setRevealGradientBounds(
+                    (width - powerButtonY) - width * interpolatedAmount,
+                    height * (1f + OFF_SCREEN_START_AMOUNT) -
+                        height * INCREASE_MULTIPLIER * interpolatedAmount,
+                    (width - powerButtonY) + width * interpolatedAmount,
+                    height * (1f + OFF_SCREEN_START_AMOUNT) +
+                        height * INCREASE_MULTIPLIER * interpolatedAmount
+                )
+            }
         }
     }
 }
@@ -208,9 +233,7 @@
  */
 class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
 
-    /**
-     * Listener that is called if the scrim's opaqueness changes
-     */
+    /** Listener that is called if the scrim's opaqueness changes */
     lateinit var isScrimOpaqueChangedListener: Consumer<Boolean>
 
     /**
@@ -224,8 +247,11 @@
 
                 revealEffect.setRevealAmountOnScrim(value, this)
                 updateScrimOpaque()
-                Trace.traceCounter(Trace.TRACE_TAG_APP, "light_reveal_amount",
-                        (field * 100).toInt())
+                Trace.traceCounter(
+                    Trace.TRACE_TAG_APP,
+                    "light_reveal_amount",
+                    (field * 100).toInt()
+                )
                 invalidate()
             }
         }
@@ -250,10 +276,10 @@
 
     /**
      * Alpha of the fill that can be used in the beginning of the animation to hide the content.
-     * Normally the gradient bounds are animated from small size so the content is not visible,
-     * but if the start gradient bounds allow to see some content this could be used to make the
-     * reveal smoother. It can help to add fade in effect in the beginning of the animation.
-     * The color of the fill is determined by [revealGradientEndColor].
+     * Normally the gradient bounds are animated from small size so the content is not visible, but
+     * if the start gradient bounds allow to see some content this could be used to make the reveal
+     * smoother. It can help to add fade in effect in the beginning of the animation. The color of
+     * the fill is determined by [revealGradientEndColor].
      *
      * 0 - no fill and content is visible, 1 - the content is covered with the start color
      */
@@ -281,9 +307,7 @@
             }
         }
 
-    /**
-     * Is the scrim currently fully opaque
-     */
+    /** Is the scrim currently fully opaque */
     var isScrimOpaque = false
         private set(value) {
             if (field != value) {
@@ -318,16 +342,22 @@
      * Paint used to draw a transparent-to-white radial gradient. This will be scaled and translated
      * via local matrix in [onDraw] so we never need to construct a new shader.
      */
-    private val gradientPaint = Paint().apply {
-        shader = RadialGradient(
-                0f, 0f, 1f,
-                intArrayOf(Color.TRANSPARENT, Color.WHITE), floatArrayOf(0f, 1f),
-                Shader.TileMode.CLAMP)
+    private val gradientPaint =
+        Paint().apply {
+            shader =
+                RadialGradient(
+                    0f,
+                    0f,
+                    1f,
+                    intArrayOf(Color.TRANSPARENT, Color.WHITE),
+                    floatArrayOf(0f, 1f),
+                    Shader.TileMode.CLAMP
+                )
 
-        // SRC_OVER ensures that we draw the semitransparent pixels over other views in the same
-        // window, rather than outright replacing them.
-        xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)
-    }
+            // SRC_OVER ensures that we draw the semitransparent pixels over other views in the same
+            // window, rather than outright replacing them.
+            xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)
+        }
 
     /**
      * Matrix applied to [gradientPaint]'s RadialGradient shader to move the gradient to
@@ -347,8 +377,8 @@
      * simply a helper method that sets [revealGradientCenter], [revealGradientWidth], and
      * [revealGradientHeight] for you.
      *
-     * This method does not call [invalidate] - you should do so once you're done changing
-     * properties.
+     * This method does not call [invalidate]
+     * - you should do so once you're done changing properties.
      */
     fun setRevealGradientBounds(left: Float, top: Float, right: Float, bottom: Float) {
         revealGradientWidth = right - left
@@ -359,8 +389,12 @@
     }
 
     override fun onDraw(canvas: Canvas?) {
-        if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0 ||
-            revealAmount == 0f) {
+        if (
+            canvas == null ||
+                revealGradientWidth <= 0 ||
+                revealGradientHeight <= 0 ||
+                revealAmount == 0f
+        ) {
             if (revealAmount < 1f) {
                 canvas?.drawColor(revealGradientEndColor)
             }
@@ -383,8 +417,10 @@
     }
 
     private fun setPaintColorFilter() {
-        gradientPaint.colorFilter = PorterDuffColorFilter(
-            getColorWithAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
-            PorterDuff.Mode.MULTIPLY)
+        gradientPaint.colorFilter =
+            PorterDuffColorFilter(
+                getColorWithAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
+                PorterDuff.Mode.MULTIPLY
+            )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java
new file mode 100644
index 0000000..39d7d66
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.systemui.shade.NotificationShadeWindowView;
+
+/**
+ * Calculates insets for the notification shade window view.
+ */
+public abstract class NotificationInsetsController
+        implements NotificationShadeWindowView.LayoutInsetsController {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsImpl.java
new file mode 100644
index 0000000..1ed704e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static android.view.WindowInsets.Type.systemBars;
+
+import android.annotation.Nullable;
+import android.graphics.Insets;
+import android.util.Pair;
+import android.view.DisplayCutout;
+import android.view.WindowInsets;
+
+import com.android.systemui.dagger.SysUISingleton;
+
+import javax.inject.Inject;
+
+/**
+ * Default implementation of NotificationsInsetsController.
+ */
+@SysUISingleton
+public class NotificationInsetsImpl extends NotificationInsetsController {
+
+    @Inject
+    public NotificationInsetsImpl() {
+
+    }
+
+    @Override
+    public Pair<Integer, Integer> getinsets(@Nullable WindowInsets windowInsets,
+            @Nullable DisplayCutout displayCutout) {
+        final Insets insets = windowInsets.getInsetsIgnoringVisibility(systemBars());
+        int leftInset = 0;
+        int rightInset = 0;
+
+        if (displayCutout != null) {
+            leftInset = displayCutout.getSafeInsetLeft();
+            rightInset = displayCutout.getSafeInsetRight();
+        }
+        leftInset = Math.max(insets.left, leftInset);
+        rightInset = Math.max(insets.right, rightInset);
+
+        return new Pair(leftInset, rightInset);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsModule.java
new file mode 100644
index 0000000..614bc0f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsModule.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.systemui.dagger.SysUISingleton;
+
+import dagger.Binds;
+import dagger.Module;
+
+@Module
+public interface NotificationInsetsModule {
+
+    @Binds
+    @SysUISingleton
+    NotificationInsetsController bindNotificationInsetsController(NotificationInsetsImpl impl);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 184dc25..cdefae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -19,7 +19,6 @@
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
-import android.app.ActivityManager;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.admin.DevicePolicyManager;
@@ -50,6 +49,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -93,6 +93,7 @@
     private final SparseBooleanArray mUsersInLockdownLatestResult = new SparseBooleanArray();
     private final SparseBooleanArray mShouldHideNotifsLatestResult = new SparseBooleanArray();
     private final UserManager mUserManager;
+    private final UserTracker mUserTracker;
     private final List<UserChangedListener> mListeners = new ArrayList<>();
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final NotificationClickNotifier mClickNotifier;
@@ -195,6 +196,7 @@
             BroadcastDispatcher broadcastDispatcher,
             DevicePolicyManager devicePolicyManager,
             UserManager userManager,
+            UserTracker userTracker,
             Lazy<NotificationVisibilityProvider> visibilityProviderLazy,
             Lazy<CommonNotifCollection> commonNotifCollectionLazy,
             NotificationClickNotifier clickNotifier,
@@ -210,7 +212,8 @@
         mMainHandler = mainHandler;
         mDevicePolicyManager = devicePolicyManager;
         mUserManager = userManager;
-        mCurrentUserId = ActivityManager.getCurrentUser();
+        mUserTracker = userTracker;
+        mCurrentUserId = mUserTracker.getUserId();
         mVisibilityProviderLazy = visibilityProviderLazy;
         mCommonNotifCollectionLazy = commonNotifCollectionLazy;
         mClickNotifier = clickNotifier;
@@ -295,7 +298,7 @@
         mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null,
                 Context.RECEIVER_EXPORTED_UNAUDITED);
 
-        mCurrentUserId = ActivityManager.getCurrentUser(); // in case we reg'd receiver too late
+        mCurrentUserId = mUserTracker.getUserId(); // in case we reg'd receiver too late
         updateCurrentProfilesCache();
 
         mSettingsObserver.onChange(false);  // set up
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 815b86e..d7eddf5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -71,6 +71,7 @@
     private int[] mTmp = new int[2];
     private boolean mHideBackground;
     private int mStatusBarHeight;
+    private boolean mEnableNotificationClipping;
     private AmbientState mAmbientState;
     private NotificationStackScrollLayoutController mHostLayoutController;
     private int mPaddingBetweenElements;
@@ -117,7 +118,7 @@
         // Setting this to first in section to get the clipping to the top roundness correct. This
         // value determines the way we are clipping to the top roundness of the overall shade
         setFirstInSection(true);
-        initDimens();
+        updateResources();
     }
 
     public void bind(AmbientState ambientState,
@@ -126,14 +127,17 @@
         mHostLayoutController = hostLayoutController;
     }
 
-    private void initDimens() {
+    private void updateResources() {
         Resources res = getResources();
         mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
 
         ViewGroup.LayoutParams layoutParams = getLayoutParams();
-        layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
-        setLayoutParams(layoutParams);
+        final int newShelfHeight = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
+        if (newShelfHeight != layoutParams.height) {
+            layoutParams.height = newShelfHeight;
+            setLayoutParams(layoutParams);
+        }
 
         final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
         mShelfIcons.setPadding(padding, 0, padding, 0);
@@ -141,6 +145,7 @@
         mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
         mCornerAnimationDistance = res.getDimensionPixelSize(
                 R.dimen.notification_corner_animation_distance);
+        mEnableNotificationClipping = res.getBoolean(R.bool.notification_enable_clipping);
 
         mShelfIcons.setInNotificationIconShelf(true);
         if (!mShowNotificationShelf) {
@@ -151,7 +156,7 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        initDimens();
+        updateResources();
     }
 
     @Override
@@ -636,7 +641,8 @@
         }
         if (!isPinned) {
             if (viewEnd > notificationClipEnd && !shouldClipOwnTop) {
-                int clipBottomAmount = (int) (viewEnd - notificationClipEnd);
+                int clipBottomAmount =
+                        mEnableNotificationClipping ? (int) (viewEnd - notificationClipEnd) : 0;
                 view.setClipBottomAmount(clipBottomAmount);
             } else {
                 view.setClipBottomAmount(0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index c070fcc..324e972 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -24,17 +24,21 @@
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
 
 import org.jetbrains.annotations.NotNull;
 
 import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 import javax.inject.Inject;
 
 /**
- *
+ * A Helper class that offloads {@link Vibrator} calls to a different thread.
+ * {@link Vibrator} makes blocking calls that may cause SysUI to ANR.
+ * TODO(b/245528624): Use regular Vibrator instance once new APIs are available.
  */
 @SysUISingleton
 public class VibratorHelper {
@@ -53,10 +57,18 @@
     private final Executor mExecutor;
 
     /**
-     *
+     * Creates a vibrator helper on a new single threaded {@link Executor}.
      */
     @Inject
-    public VibratorHelper(@Nullable Vibrator vibrator, @Background Executor executor) {
+    public VibratorHelper(@Nullable Vibrator vibrator) {
+        this(vibrator, Executors.newSingleThreadExecutor());
+    }
+
+    /**
+     * Creates new vibrator helper on a specific {@link Executor}.
+     */
+    @VisibleForTesting
+    public VibratorHelper(@Nullable Vibrator vibrator, Executor executor) {
         mExecutor = executor;
         mVibrator = vibrator;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
index 5cf1abc..035b90f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
@@ -15,9 +15,7 @@
  */
 package com.android.systemui.statusbar.connectivity;
 
-import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons;
-import static com.android.settingslib.mobile.MobileMappings.getIconKey;
-import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
 
 import android.content.Context;
 import android.content.Intent;
@@ -46,6 +44,7 @@
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy;
 import com.android.systemui.util.CarrierConfigTracker;
 
 import java.io.PrintWriter;
@@ -63,6 +62,7 @@
     private final TelephonyManager mPhone;
     private final CarrierConfigTracker mCarrierConfigTracker;
     private final SubscriptionDefaults mDefaults;
+    private final MobileMappingsProxy mMobileMappingsProxy;
     private final String mNetworkNameDefault;
     private final String mNetworkNameSeparator;
     private final ContentObserver mObserver;
@@ -121,6 +121,7 @@
             TelephonyManager phone,
             CallbackHandler callbackHandler,
             NetworkControllerImpl networkController,
+            MobileMappingsProxy mobileMappingsProxy,
             SubscriptionInfo info,
             SubscriptionDefaults defaults,
             Looper receiverLooper,
@@ -135,13 +136,14 @@
         mPhone = phone;
         mDefaults = defaults;
         mSubscriptionInfo = info;
+        mMobileMappingsProxy = mobileMappingsProxy;
         mNetworkNameSeparator = getTextIfExists(
                 R.string.status_bar_network_name_separator).toString();
         mNetworkNameDefault = getTextIfExists(
                 com.android.internal.R.string.lockscreen_carrier_default).toString();
 
-        mNetworkToIconLookup = mapIconSets(mConfig);
-        mDefaultIcons = getDefaultIcons(mConfig);
+        mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
+        mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
 
         String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
                 : mNetworkNameDefault;
@@ -161,8 +163,8 @@
     void setConfiguration(Config config) {
         mConfig = config;
         updateInflateSignalStrength();
-        mNetworkToIconLookup = mapIconSets(mConfig);
-        mDefaultIcons = getDefaultIcons(mConfig);
+        mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
+        mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
         updateTelephony();
     }
 
@@ -271,8 +273,9 @@
             dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
         }
 
-        final QsInfo qsInfo = getQsInfo(contentDescription, icons.dataType);
-        final SbInfo sbInfo = getSbInfo(contentDescription, icons.dataType);
+        int iconId = mCurrentState.getNetworkTypeIcon(mContext);
+        final QsInfo qsInfo = getQsInfo(contentDescription, iconId);
+        final SbInfo sbInfo = getSbInfo(contentDescription, iconId);
 
         MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
                 sbInfo.icon,
@@ -373,6 +376,10 @@
         } else if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
             updateDataSim();
             notifyListenersIfNecessary();
+        } else if (action.equals(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED)) {
+            int carrierId = intent.getIntExtra(
+                    TelephonyManager.EXTRA_CARRIER_ID, UNKNOWN_CARRIER_ID);
+            mCurrentState.setCarrierId(carrierId);
         }
     }
 
@@ -477,7 +484,8 @@
             mCurrentState.level = getSignalLevel(mCurrentState.signalStrength);
         }
 
-        String iconKey = getIconKey(mCurrentState.telephonyDisplayInfo);
+        mCurrentState.setCarrierId(mPhone.getSimCarrierId());
+        String iconKey = mMobileMappingsProxy.getIconKey(mCurrentState.telephonyDisplayInfo);
         if (mNetworkToIconLookup.get(iconKey) != null) {
             mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
index 7938179..a323454 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
@@ -22,6 +22,7 @@
 import com.android.settingslib.mobile.MobileMappings
 import com.android.settingslib.mobile.MobileStatusTracker
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 import com.android.systemui.util.CarrierConfigTracker
 import javax.inject.Inject
 
@@ -33,6 +34,7 @@
     val context: Context,
     val callbackHandler: CallbackHandler,
     val carrierConfigTracker: CarrierConfigTracker,
+    val mobileMappings: MobileMappingsProxy,
 ) {
     fun createMobileSignalController(
         config: MobileMappings.Config,
@@ -56,6 +58,7 @@
             phone,
             callbackHandler,
             networkController,
+            mobileMappings,
             subscriptionInfo,
             subscriptionDefaults,
             receiverLooper,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
index f20d206..1fb6a98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
@@ -16,10 +16,14 @@
 
 package com.android.systemui.statusbar.connectivity
 
+import android.annotation.DrawableRes
+import android.content.Context
 import android.telephony.ServiceState
 import android.telephony.SignalStrength
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyManager
+import com.android.internal.annotations.VisibleForTesting
+import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.settingslib.Utils
 import com.android.settingslib.mobile.MobileStatusTracker.MobileStatus
 import com.android.settingslib.mobile.TelephonyIcons
@@ -41,7 +45,7 @@
     @JvmField var roaming: Boolean = false,
     @JvmField var dataState: Int = TelephonyManager.DATA_DISCONNECTED,
     // Tracks the on/off state of the defaultDataSubscription
-    @JvmField var defaultDataOff: Boolean = false
+    @JvmField var defaultDataOff: Boolean = false,
 ) : ConnectivityState() {
 
     @JvmField var telephonyDisplayInfo = TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -49,6 +53,11 @@
     @JvmField var serviceState: ServiceState? = null
     @JvmField var signalStrength: SignalStrength? = null
 
+    var carrierId = TelephonyManager.UNKNOWN_CARRIER_ID
+
+    @VisibleForTesting
+    var networkTypeResIdCache: NetworkTypeResIdCache = NetworkTypeResIdCache()
+
     /** @return true if this state is disabled or not default data */
     val isDataDisabledOrNotDefault: Boolean
         get() = (iconGroup === TelephonyIcons.DATA_DISABLED ||
@@ -125,6 +134,21 @@
         return serviceState != null && serviceState!!.roaming
     }
 
+    /**
+     *
+     * Load the (potentially customized) icon resource id for the current network type. Note that
+     * this operation caches the result. Note that reading the [MobileIconGroup.dataType] field
+     * directly will not yield correct results in cases where the carrierId has an associated
+     * override. This is the preferred method for getting the network type indicator.
+     *
+     * @return a drawable res id appropriate for the current (carrierId, networkType) pair
+     */
+    @DrawableRes
+    fun getNetworkTypeIcon(context: Context): Int {
+        val icon = (iconGroup as MobileIconGroup)
+        return networkTypeResIdCache.get(icon, carrierId, context)
+    }
+
     fun setFromMobileStatus(mobileStatus: MobileStatus) {
         activityIn = mobileStatus.activityIn
         activityOut = mobileStatus.activityOut
@@ -140,6 +164,7 @@
         super.toString(builder)
         builder.append(',')
         builder.append("dataSim=$dataSim,")
+        builder.append("carrierId=$carrierId")
         builder.append("networkName=$networkName,")
         builder.append("networkNameData=$networkNameData,")
         builder.append("dataConnected=$dataConnected,")
@@ -157,6 +182,8 @@
         builder.append("voiceServiceState=${getVoiceServiceState()},")
         builder.append("isInService=${isInService()},")
 
+        builder.append("networkTypeIconCache=$networkTypeResIdCache")
+
         builder.append("serviceState=${serviceState?.minLog() ?: "(null)"},")
         builder.append("signalStrength=${signalStrength?.minLog() ?: "(null)"},")
         builder.append("displayInfo=$telephonyDisplayInfo")
@@ -164,6 +191,7 @@
 
     override fun tableColumns(): List<String> {
         val columns = listOf("dataSim",
+            "carrierId",
             "networkName",
             "networkNameData",
             "dataConnected",
@@ -178,6 +206,7 @@
             "showQuickSettingsRatIcon",
             "voiceServiceState",
             "isInService",
+            "networkTypeIconCache",
             "serviceState",
             "signalStrength",
             "displayInfo")
@@ -187,6 +216,7 @@
 
     override fun tableData(): List<String> {
         val columns = listOf(dataSim,
+                carrierId,
                 networkName,
                 networkNameData,
                 dataConnected,
@@ -201,6 +231,7 @@
                 showQuickSettingsRatIcon(),
                 getVoiceServiceState(),
                 isInService(),
+                networkTypeResIdCache,
                 serviceState?.minLog() ?: "(null)",
                 signalStrength?.minLog() ?: "(null)",
                 telephonyDisplayInfo).map { it.toString() }
@@ -217,6 +248,7 @@
 
         if (networkName != other.networkName) return false
         if (networkNameData != other.networkNameData) return false
+        if (carrierId != other.carrierId) return false
         if (dataSim != other.dataSim) return false
         if (dataConnected != other.dataConnected) return false
         if (isEmergency != other.isEmergency) return false
@@ -238,6 +270,7 @@
         var result = super.hashCode()
         result = 31 * result + (networkName?.hashCode() ?: 0)
         result = 31 * result + (networkNameData?.hashCode() ?: 0)
+        result = 31 * result + (carrierId.hashCode())
         result = 31 * result + dataSim.hashCode()
         result = 31 * result + dataConnected.hashCode()
         result = 31 * result + isEmergency.hashCode()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 402217d..fe488a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -22,6 +22,7 @@
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
 import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -38,6 +39,7 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
@@ -75,7 +77,7 @@
 import com.android.systemui.plugins.log.LogBuffer;
 import com.android.systemui.plugins.log.LogLevel;
 import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DataSaverControllerImpl;
@@ -128,7 +130,7 @@
     private final boolean mHasMobileDataFeature;
     private final SubscriptionDefaults mSubDefaults;
     private final DataSaverController mDataSaverController;
-    private final CurrentUserTracker mUserTracker;
+    private final UserTracker mUserTracker;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final DemoModeController mDemoModeController;
     private final Object mLock = new Object();
@@ -139,7 +141,7 @@
     private final MobileSignalControllerFactory mMobileFactory;
 
     private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
-    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private int mActiveMobileDataSubscription = INVALID_SUBSCRIPTION_ID;
 
     // Subcontrollers.
     @VisibleForTesting
@@ -212,6 +214,14 @@
                 }
             };
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    NetworkControllerImpl.this.onUserSwitched(newUser);
+                }
+            };
+
     /**
      * Construct this controller object and register for updates.
      */
@@ -224,6 +234,7 @@
             CallbackHandler callbackHandler,
             DeviceProvisionedController deviceProvisionedController,
             BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
             ConnectivityManager connectivityManager,
             TelephonyManager telephonyManager,
             TelephonyListenerManager telephonyListenerManager,
@@ -251,6 +262,7 @@
                 new SubscriptionDefaults(),
                 deviceProvisionedController,
                 broadcastDispatcher,
+                userTracker,
                 demoModeController,
                 carrierConfigTracker,
                 trackerFactory,
@@ -277,6 +289,7 @@
             SubscriptionDefaults defaultsHandler,
             DeviceProvisionedController deviceProvisionedController,
             BroadcastDispatcher broadcastDispatcher,
+            UserTracker userTracker,
             DemoModeController demoModeController,
             CarrierConfigTracker carrierConfigTracker,
             WifiStatusTrackerFactory trackerFactory,
@@ -333,13 +346,9 @@
 
         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
         updateAirplaneMode(true /* force callback */);
-        mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                NetworkControllerImpl.this.onUserSwitched(newUserId);
-            }
-        };
-        mUserTracker.startTracking();
+        mUserTracker = userTracker;
+        mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(mMainHandler));
+
         deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
             @Override
             public void onUserSetupChanged() {
@@ -503,6 +512,7 @@
         filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
         filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
+        filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler);
         mListening = true;
@@ -793,6 +803,20 @@
                 mConfig = Config.readConfig(mContext);
                 mReceiverHandler.post(this::handleConfigurationChanged);
                 break;
+
+            case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: {
+                // Notify the relevant MobileSignalController of the change
+                int subId = intent.getIntExtra(
+                        TelephonyManager.EXTRA_SUBSCRIPTION_ID,
+                        INVALID_SUBSCRIPTION_ID
+                );
+                if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                    if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
+                        mMobileSignalControllers.get(subId).handleBroadcast(intent);
+                    }
+                }
+            }
+            break;
             case Intent.ACTION_SIM_STATE_CHANGED:
                 // Avoid rebroadcast because SysUI is direct boot aware.
                 if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
@@ -820,7 +844,7 @@
                 break;
             default:
                 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
-                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                        INVALID_SUBSCRIPTION_ID);
                 if (SubscriptionManager.isValidSubscriptionId(subId)) {
                     if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                         mMobileSignalControllers.get(subId).handleBroadcast(intent);
@@ -1336,6 +1360,9 @@
             String slotString = args.getString("slot");
             int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
             slot = MathUtils.constrain(slot, 0, 8);
+            String carrierIdString = args.getString("carrierid");
+            int carrierId = TextUtils.isEmpty(carrierIdString) ? 0
+                    : Integer.parseInt(carrierIdString);
             // Ensure we have enough sim slots
             List<SubscriptionInfo> subs = new ArrayList<>();
             while (mMobileSignalControllers.size() <= slot) {
@@ -1347,6 +1374,9 @@
             }
             // Hack to index linearly for easy use.
             MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
+            if (carrierId != 0) {
+                controller.getState().setCarrierId(carrierId);
+            }
             controller.getState().dataSim = datatype != null;
             controller.getState().isDefault = datatype != null;
             controller.getState().dataConnected = datatype != null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt
new file mode 100644
index 0000000..9be7ee9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.connectivity
+
+import android.annotation.DrawableRes
+import android.content.Context
+import com.android.settingslib.SignalIcon.MobileIconGroup
+import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
+import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl
+
+/**
+ * Cache for network type resource IDs.
+ *
+ * The default framework behavior is to have a statically defined icon per network type. See
+ * [MobileIconGroup] for the standard mapping.
+ *
+ * For the case of carrierId-defined overrides, we want to check [MobileIconCarrierIdOverrides] for
+ * an existing icon override, and cache the result of the operation
+ */
+class NetworkTypeResIdCache(
+    private val overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl()
+) {
+    @DrawableRes private var cachedResId: Int = 0
+    private var lastCarrierId: Int? = null
+    private var lastIconGroup: MobileIconGroup? = null
+    private var isOverridden: Boolean = false
+
+    @DrawableRes
+    fun get(iconGroup: MobileIconGroup, carrierId: Int, context: Context): Int {
+        if (lastCarrierId != carrierId || lastIconGroup != iconGroup) {
+            lastCarrierId = carrierId
+            lastIconGroup = iconGroup
+
+            val maybeOverride = calculateOverriddenIcon(iconGroup, carrierId, context)
+            if (maybeOverride > 0) {
+                cachedResId = maybeOverride
+                isOverridden = true
+            } else {
+                cachedResId = iconGroup.dataType
+                isOverridden = false
+            }
+        }
+
+        return cachedResId
+    }
+
+    override fun toString(): String {
+        return "networkTypeResIdCache={id=$cachedResId, isOverridden=$isOverridden}"
+    }
+
+    @DrawableRes
+    private fun calculateOverriddenIcon(
+        iconGroup: MobileIconGroup,
+        carrierId: Int,
+        context: Context,
+    ): Int {
+        val name = iconGroup.name
+        if (!overrides.carrierIdEntryExists(carrierId)) {
+            return 0
+        }
+
+        return overrides.getOverrideFor(carrierId, name, context.resources)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index a02dd34..42b874f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -37,6 +37,13 @@
  * own [Configuration] and track resources based on the full set of available mcc-mnc combinations.
  *
  * (for future reference: b/240555502 is the initiating bug for this)
+ *
+ * NOTE: MCC/MNC qualifiers are not sufficient to fully describe a network type icon qualified by
+ * network type + carrier ID. This class exists to keep the legacy behavior of using the MCC/MNC
+ * resource qualifiers working, but if a carrier-specific icon is requested, then the override
+ * provided by [MobileIconCarrierIdOverrides] will take precedence.
+ *
+ * TODO(b/258503704): consider removing this class in favor of the `carrierId` overrides
  */
 @SysUISingleton
 class MobileContextProvider
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 e4a8f21..c6911b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -234,19 +234,24 @@
 
         ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
             override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
-                activityStarter.startActivity(
-                    intent,
-                    true, /* dismissShade */
-                    null, /* launch animator - looks bad with the transparent smartspace bg */
-                    showOnLockscreen
-                )
+                if (showOnLockscreen) {
+                    activityStarter.startActivity(
+                            intent,
+                            true, /* dismissShade */
+                            // launch animator - looks bad with the transparent smartspace bg
+                            null,
+                            true
+                    )
+                } else {
+                    activityStarter.postStartActivityDismissingKeyguard(intent, 0)
+                }
             }
 
             override fun startPendingIntent(pi: PendingIntent, showOnLockscreen: Boolean) {
                 if (showOnLockscreen) {
                     pi.send()
                 } else {
-                    activityStarter.startPendingIntentDismissingKeyguard(pi)
+                    activityStarter.postStartActivityDismissingKeyguard(pi)
                 }
             }
         })
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index 2734511..7eb8906 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -40,4 +40,8 @@
     val isSemiStableSortEnabled: Boolean by lazy {
         featureFlags.isEnabled(Flags.SEMI_STABLE_SORT)
     }
+
+    val shouldFilterUnseenNotifsOnKeyguard: Boolean by lazy {
+        featureFlags.isEnabled(Flags.FILTER_UNSEEN_NOTIFS_ON_KEYGUARD)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
deleted file mode 100644
index e3d71c8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection.coordinator;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
-import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider;
-import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
-
-import javax.inject.Inject;
-
-/**
- * Filters low priority and privacy-sensitive notifications from the lockscreen, and hides section
- * headers on the lockscreen.
- */
-@CoordinatorScope
-public class KeyguardCoordinator implements Coordinator {
-    private static final String TAG = "KeyguardCoordinator";
-    private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
-    private final SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider;
-    private final StatusBarStateController mStatusBarStateController;
-
-    @Inject
-    public KeyguardCoordinator(
-            KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
-            SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider,
-            StatusBarStateController statusBarStateController) {
-        mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
-        mSectionHeaderVisibilityProvider = sectionHeaderVisibilityProvider;
-        mStatusBarStateController = statusBarStateController;
-    }
-
-    @Override
-    public void attach(NotifPipeline pipeline) {
-
-        setupInvalidateNotifListCallbacks();
-        // Filter at the "finalize" stage so that views remain bound by PreparationCoordinator
-        pipeline.addFinalizeFilter(mNotifFilter);
-        mKeyguardNotificationVisibilityProvider
-                .addOnStateChangedListener(this::invalidateListFromFilter);
-        updateSectionHeadersVisibility();
-    }
-
-    private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
-        @Override
-        public boolean shouldFilterOut(@NonNull NotificationEntry entry, long now) {
-            return mKeyguardNotificationVisibilityProvider.shouldHideNotification(entry);
-        }
-    };
-
-    // TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on
-    // these same updates
-    private void setupInvalidateNotifListCallbacks() {
-
-    }
-
-    private void invalidateListFromFilter(String reason) {
-        updateSectionHeadersVisibility();
-        mNotifFilter.invalidateList(reason);
-    }
-
-    private void updateSectionHeadersVisibility() {
-        boolean onKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
-        boolean neverShowSections = mSectionHeaderVisibilityProvider.getNeverShowSectionHeaders();
-        boolean showSections = !onKeyguard && !neverShowSections;
-        mSectionHeaderVisibilityProvider.setSectionHeadersVisible(showSections);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
new file mode 100644
index 0000000..6e5fceb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
+import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+
+/**
+ * Filters low priority and privacy-sensitive notifications from the lockscreen, and hides section
+ * headers on the lockscreen.
+ */
+@CoordinatorScope
+class KeyguardCoordinator
+@Inject
+constructor(
+    private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
+    private val keyguardRepository: KeyguardRepository,
+    private val notifPipelineFlags: NotifPipelineFlags,
+    @Application private val scope: CoroutineScope,
+    private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
+    private val statusBarStateController: StatusBarStateController,
+) : Coordinator {
+
+    private val unseenNotifications = mutableSetOf<NotificationEntry>()
+
+    override fun attach(pipeline: NotifPipeline) {
+        setupInvalidateNotifListCallbacks()
+        // Filter at the "finalize" stage so that views remain bound by PreparationCoordinator
+        pipeline.addFinalizeFilter(notifFilter)
+        keyguardNotificationVisibilityProvider.addOnStateChangedListener(::invalidateListFromFilter)
+        updateSectionHeadersVisibility()
+        if (notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard) {
+            attachUnseenFilter(pipeline)
+        }
+    }
+
+    private fun attachUnseenFilter(pipeline: NotifPipeline) {
+        pipeline.addFinalizeFilter(unseenNotifFilter)
+        pipeline.addCollectionListener(collectionListener)
+        scope.launch { clearUnseenWhenKeyguardIsDismissed() }
+    }
+
+    private suspend fun clearUnseenWhenKeyguardIsDismissed() {
+        // Use collectLatest so that the suspending block is cancelled if isKeyguardShowing changes
+        // during the timeout period
+        keyguardRepository.isKeyguardShowing.collectLatest { isKeyguardShowing ->
+            if (!isKeyguardShowing) {
+                unseenNotifFilter.invalidateList("keyguard no longer showing")
+                delay(SEEN_TIMEOUT)
+                unseenNotifications.clear()
+            }
+        }
+    }
+
+    private val collectionListener =
+        object : NotifCollectionListener {
+            override fun onEntryAdded(entry: NotificationEntry) {
+                if (keyguardRepository.isKeyguardShowing()) {
+                    unseenNotifications.add(entry)
+                }
+            }
+
+            override fun onEntryUpdated(entry: NotificationEntry) {
+                if (keyguardRepository.isKeyguardShowing()) {
+                    unseenNotifications.add(entry)
+                }
+            }
+
+            override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+                unseenNotifications.remove(entry)
+            }
+        }
+
+    @VisibleForTesting
+    internal val unseenNotifFilter =
+        object : NotifFilter("$TAG-unseen") {
+            override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean =
+                when {
+                    // Don't apply filter if the keyguard isn't currently showing
+                    !keyguardRepository.isKeyguardShowing() -> false
+                    // Don't apply the filter if the notification is unseen
+                    unseenNotifications.contains(entry) -> false
+                    // Don't apply the filter to (non-promoted) group summaries
+                    //  - summary will be pruned if necessary, depending on if children are filtered
+                    entry.parent?.summary == entry -> false
+                    else -> true
+                }
+        }
+
+    private val notifFilter: NotifFilter =
+        object : NotifFilter(TAG) {
+            override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean =
+                keyguardNotificationVisibilityProvider.shouldHideNotification(entry)
+        }
+
+    // TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on
+    //  these same updates
+    private fun setupInvalidateNotifListCallbacks() {}
+
+    private fun invalidateListFromFilter(reason: String) {
+        updateSectionHeadersVisibility()
+        notifFilter.invalidateList(reason)
+    }
+
+    private fun updateSectionHeadersVisibility() {
+        val onKeyguard = statusBarStateController.state == StatusBarState.KEYGUARD
+        val neverShowSections = sectionHeaderVisibilityProvider.neverShowSectionHeaders
+        val showSections = !onKeyguard && !neverShowSections
+        sectionHeaderVisibilityProvider.sectionHeadersVisible = showSections
+    }
+
+    companion object {
+        private const val TAG = "KeyguardCoordinator"
+        private val SEEN_TIMEOUT = 5.seconds
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 3002a68..a2379b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -29,6 +29,7 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeStateEvents;
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -62,6 +63,7 @@
     private final HeadsUpManager mHeadsUpManager;
     private final ShadeStateEvents mShadeStateEvents;
     private final StatusBarStateController mStatusBarStateController;
+    private final VisibilityLocationProvider mVisibilityLocationProvider;
     private final VisualStabilityProvider mVisualStabilityProvider;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
 
@@ -94,9 +96,11 @@
             HeadsUpManager headsUpManager,
             ShadeStateEvents shadeStateEvents,
             StatusBarStateController statusBarStateController,
+            VisibilityLocationProvider visibilityLocationProvider,
             VisualStabilityProvider visualStabilityProvider,
             WakefulnessLifecycle wakefulnessLifecycle) {
         mHeadsUpManager = headsUpManager;
+        mVisibilityLocationProvider = visibilityLocationProvider;
         mVisualStabilityProvider = visualStabilityProvider;
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mStatusBarStateController = statusBarStateController;
@@ -123,6 +127,11 @@
     //  HUNs to the top of the shade
     private final NotifStabilityManager mNotifStabilityManager =
             new NotifStabilityManager("VisualStabilityCoordinator") {
+                private boolean canMoveForHeadsUp(NotificationEntry entry) {
+                    return entry != null && mHeadsUpManager.isAlerting(entry.getKey())
+                            && !mVisibilityLocationProvider.isInVisibleLocation(entry);
+                }
+
                 @Override
                 public void onBeginRun() {
                     mIsSuppressingPipelineRun = false;
@@ -140,7 +149,7 @@
                 @Override
                 public boolean isGroupChangeAllowed(@NonNull NotificationEntry entry) {
                     final boolean isGroupChangeAllowedForEntry =
-                            mReorderingAllowed || mHeadsUpManager.isAlerting(entry.getKey());
+                            mReorderingAllowed || canMoveForHeadsUp(entry);
                     mIsSuppressingGroupChange |= !isGroupChangeAllowedForEntry;
                     return isGroupChangeAllowedForEntry;
                 }
@@ -156,7 +165,7 @@
                 public boolean isSectionChangeAllowed(@NonNull NotificationEntry entry) {
                     final boolean isSectionChangeAllowedForEntry =
                             mReorderingAllowed
-                                    || mHeadsUpManager.isAlerting(entry.getKey())
+                                    || canMoveForHeadsUp(entry)
                                     || mEntriesThatCanChangeSection.containsKey(entry.getKey());
                     if (!isSectionChangeAllowedForEntry) {
                         mEntriesWithSuppressedSectionChange.add(entry.getKey());
@@ -165,8 +174,8 @@
                 }
 
                 @Override
-                public boolean isEntryReorderingAllowed(@NonNull ListEntry section) {
-                    return mReorderingAllowed;
+                public boolean isEntryReorderingAllowed(@NonNull ListEntry entry) {
+                    return mReorderingAllowed || canMoveForHeadsUp(entry.getRepresentativeEntry());
                 }
 
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisibilityLocationProviderDelegator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisibilityLocationProviderDelegator.kt
new file mode 100644
index 0000000..4bc4ecf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisibilityLocationProviderDelegator.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.provider
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import javax.inject.Inject
+
+/**
+ * An injectable component which delegates the visibility location computation to a delegate which
+ * can be initialized after the initial injection, generally because it's provided by a view.
+ */
+@SysUISingleton
+class VisibilityLocationProviderDelegator @Inject constructor() : VisibilityLocationProvider {
+    private var delegate: VisibilityLocationProvider? = null
+
+    fun setDelegate(provider: VisibilityLocationProvider) {
+        delegate = provider
+    }
+
+    override fun isInVisibleLocation(entry: NotificationEntry): Boolean =
+        requireNotNull(this.delegate) { "delegate not initialized" }.isInVisibleLocation(entry)
+}
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 df2de56..a7b7a23 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
@@ -37,6 +37,7 @@
 import com.android.systemui.shade.ShadeExpansionStateManager;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
 import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl;
@@ -51,6 +52,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
 import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl;
+import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -151,6 +153,11 @@
     @Binds
     NotifGutsViewManager bindNotifGutsViewManager(NotificationGutsManager notificationGutsManager);
 
+    /** Provides an instance of {@link VisibilityLocationProvider} */
+    @Binds
+    VisibilityLocationProvider bindVisibilityLocationProvider(
+            VisibilityLocationProviderDelegator visibilityLocationProviderDelegator);
+
     /** Provides an instance of {@link NotificationLogger} */
     @SysUISingleton
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 3021414..b93e150 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -135,6 +135,8 @@
 
     private static final String TAG = "ExpandableNotifRow";
     private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean DEBUG_ONMEASURE =
+            Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
     private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
     private static final int COLORED_DIVIDER_ALPHA = 0x7B;
     private static final int MENU_VIEW_INDEX = 0;
@@ -1724,6 +1726,11 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         Trace.beginSection(appendTraceStyleTag("ExpNotRow#onMeasure"));
+        if (DEBUG_ONMEASURE) {
+            Log.d(TAG, "onMeasure("
+                    + "widthMeasureSpec=" + MeasureSpec.toString(widthMeasureSpec) + ", "
+                    + "heightMeasureSpec=" + MeasureSpec.toString(heightMeasureSpec) + ")");
+        }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         Trace.endSection();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 645a02d..d43ca823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -25,6 +25,7 @@
 import android.graphics.Path;
 import android.graphics.Path.Direction;
 import android.graphics.drawable.ColorDrawable;
+import android.os.Trace;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -219,6 +220,7 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        Trace.beginSection("NotificationChildrenContainer#onMeasure");
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
         boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
         boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
@@ -267,6 +269,7 @@
         }
 
         setMeasuredDimension(width, height);
+        Trace.endSection();
     }
 
     @Override
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 2c3330e..41dbf1d 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
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import static android.os.Trace.TRACE_TAG_ALWAYS;
+
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
@@ -44,6 +46,7 @@
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.Trace;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.IndentingPrintWriter;
@@ -1074,6 +1077,12 @@
     @Override
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        Trace.beginSection("NotificationStackScrollLayout#onMeasure");
+        if (SPEW) {
+            Log.d(TAG, "onMeasure("
+                    + "widthMeasureSpec=" + MeasureSpec.toString(widthMeasureSpec) + ", "
+                    + "heightMeasureSpec=" + MeasureSpec.toString(heightMeasureSpec) + ")");
+        }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
         int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -1090,6 +1099,13 @@
         for (int i = 0; i < size; i++) {
             measureChild(getChildAt(i), childWidthSpec, childHeightSpec);
         }
+        Trace.endSection();
+    }
+
+    @Override
+    public void requestLayout() {
+        Trace.instant(TRACE_TAG_ALWAYS, "NotificationStackScrollLayout#requestLayout");
+        super.requestLayout();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index e1337826..0240bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -89,6 +89,7 @@
 import com.android.systemui.statusbar.notification.collection.PipelineDumper;
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
 import com.android.systemui.statusbar.notification.collection.render.NotifStats;
@@ -157,6 +158,7 @@
     private final NotifCollection mNotifCollection;
     private final UiEventLogger mUiEventLogger;
     private final NotificationRemoteInputManager mRemoteInputManager;
+    private final VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
     private final ShadeController mShadeController;
     private final KeyguardMediaController mKeyguardMediaController;
     private final SysuiStatusBarStateController mStatusBarStateController;
@@ -638,6 +640,7 @@
             ShadeTransitionController shadeTransitionController,
             UiEventLogger uiEventLogger,
             NotificationRemoteInputManager remoteInputManager,
+            VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
             ShadeController shadeController,
             InteractionJankMonitor jankMonitor,
             StackStateLogger stackLogger,
@@ -679,6 +682,7 @@
         mNotifCollection = notifCollection;
         mUiEventLogger = uiEventLogger;
         mRemoteInputManager = remoteInputManager;
+        mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
         mShadeController = shadeController;
         mFeatureFlags = featureFlags;
         mNotificationTargetsHelper = notificationTargetsHelper;
@@ -750,6 +754,8 @@
         mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate);
         mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded);
 
+        mVisibilityLocationProviderDelegator.setDelegate(this::isInVisibleLocation);
+
         mTunerService.addTunable(
                 (key, newValue) -> {
                     switch (key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index eea1d911..62f57b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -57,6 +57,7 @@
     private float mGapHeight;
     private float mGapHeightOnLockscreen;
     private int mCollapsedSize;
+    private boolean mEnableNotificationClipping;
 
     private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
     private boolean mIsExpanded;
@@ -85,6 +86,7 @@
         mPaddingBetweenElements = res.getDimensionPixelSize(
                 R.dimen.notification_divider_height);
         mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mEnableNotificationClipping = res.getBoolean(R.bool.notification_enable_clipping);
         mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
         int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
         mHeadsUpInset = statusBarHeight + res.getDimensionPixelSize(
@@ -289,7 +291,7 @@
                 // The bottom of this view is peeking out from under the previous view.
                 // Clip the part that is peeking out.
                 float overlapAmount = newNotificationEnd - firstHeadsUpEnd;
-                state.clipBottomAmount = (int) overlapAmount;
+                state.clipBottomAmount = mEnableNotificationClipping ? (int) overlapAmount : 0;
             } else {
                 state.clipBottomAmount = 0;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index bd0678f..3557b4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -54,7 +54,6 @@
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.LightRevealScrim;
 import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 
 import java.io.PrintWriter;
 
@@ -254,8 +253,6 @@
 
     boolean isWakeUpComingFromTouch();
 
-    boolean isFalsingThresholdNeeded();
-
     void onKeyguardViewManagerStatesUpdated();
 
     ViewGroup getNotificationScrollLayout();
@@ -413,12 +410,6 @@
 
     void onClosingFinished();
 
-    void onUnlockHintStarted();
-
-    void onHintFinished();
-
-    void onTrackingStopped(boolean expand);
-
     // TODO: Figure out way to remove these.
     NavigationBarView getNavigationBarView();
 
@@ -500,8 +491,6 @@
 
     boolean isKeyguardSecure();
 
-    NotificationGutsManager getGutsManager();
-
     void updateNotificationPanelTouchState();
 
     void makeExpandedVisible(boolean force);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 1e95dad..9e5a66f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -55,6 +55,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -71,6 +72,8 @@
 
 import javax.inject.Inject;
 
+import dagger.Lazy;
+
 /** */
 @CentralSurfacesComponent.CentralSurfacesScope
 public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callbacks {
@@ -99,6 +102,7 @@
     private final boolean mVibrateOnOpening;
     private final VibrationEffect mCameraLaunchGestureVibrationEffect;
     private final SystemBarAttributesListener mSystemBarAttributesListener;
+    private final Lazy<CameraLauncher> mCameraLauncherLazy;
 
     private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
             VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
@@ -128,8 +132,8 @@
             Optional<Vibrator> vibratorOptional,
             DisableFlagsLogger disableFlagsLogger,
             @DisplayId int displayId,
-            SystemBarAttributesListener systemBarAttributesListener) {
-
+            SystemBarAttributesListener systemBarAttributesListener,
+            Lazy<CameraLauncher> cameraLauncherLazy) {
         mCentralSurfaces = centralSurfaces;
         mContext = context;
         mShadeController = shadeController;
@@ -152,6 +156,7 @@
         mVibratorOptional = vibratorOptional;
         mDisableFlagsLogger = disableFlagsLogger;
         mDisplayId = displayId;
+        mCameraLauncherLazy = cameraLauncherLazy;
 
         mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation);
         mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
@@ -346,7 +351,8 @@
             mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true);
             return;
         }
-        if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
+        if (!mCameraLauncherLazy.get().canCameraGestureBeLaunched(
+                mNotificationPanelViewController.getBarState())) {
             if (CentralSurfaces.DEBUG_CAMERA_LIFT) {
                 Slog.d(CentralSurfaces.TAG, "Can't launch camera right now");
             }
@@ -383,7 +389,8 @@
                 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                     mStatusBarKeyguardViewManager.reset(true /* hide */);
                 }
-                mNotificationPanelViewController.launchCamera(source);
+                mCameraLauncherLazy.get().launchCamera(source,
+                        mNotificationPanelViewController.isFullyCollapsed());
                 mCentralSurfaces.updateScrimController();
             } else {
                 // We need to defer the camera launch until the screen comes on, since otherwise
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 37027ea..a592da4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -174,9 +174,9 @@
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.ripple.RippleShader.RippleShape;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.NotificationShadeWindowView;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -233,6 +233,7 @@
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.window.StatusBarWindowController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
 import com.android.systemui.util.DumpUtilsKt;
 import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -280,6 +281,7 @@
     // 1020-1040 reserved for BaseStatusBar
 
     /**
+     * TODO(b/249277686) delete this
      * The delay to reset the hint text when the hint animation is finished running.
      */
     private static final int HINT_RESET_DELAY_MS = 1200;
@@ -485,6 +487,7 @@
     private final PluginManager mPluginManager;
     private final ShadeController mShadeController;
     private final InitController mInitController;
+    private final Lazy<CameraLauncher> mCameraLauncherLazy;
 
     private final PluginDependencyProvider mPluginDependencyProvider;
     private final KeyguardDismissUtil mKeyguardDismissUtil;
@@ -617,6 +620,7 @@
 
     private Runnable mLaunchTransitionEndRunnable;
     private Runnable mLaunchTransitionCancelRunnable;
+    private boolean mLaunchingAffordance;
     private boolean mLaunchCameraWhenFinishedWaking;
     private boolean mLaunchCameraOnFinishedGoingToSleep;
     private boolean mLaunchEmergencyActionWhenFinishedWaking;
@@ -761,7 +765,8 @@
             InteractionJankMonitor jankMonitor,
             DeviceStateManager deviceStateManager,
             WiredChargingRippleController wiredChargingRippleController,
-            IDreamManager dreamManager) {
+            IDreamManager dreamManager,
+            Lazy<CameraLauncher> cameraLauncherLazy) {
         mContext = context;
         mNotificationsController = notificationsController;
         mFragmentService = fragmentService;
@@ -838,6 +843,7 @@
         mMessageRouter = messageRouter;
         mWallpaperManager = wallpaperManager;
         mJankMonitor = jankMonitor;
+        mCameraLauncherLazy = cameraLauncherLazy;
 
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
         mStartingSurfaceOptional = startingSurfaceOptional;
@@ -1143,7 +1149,6 @@
         // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
         mNotificationIconAreaController.setupShelf(mNotificationShelfController);
         mShadeExpansionStateManager.addExpansionListener(mWakeUpCoordinator);
-        mUserSwitcherController.init(mNotificationShadeWindowView);
 
         // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
         mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
@@ -1798,11 +1803,6 @@
         return mWakeUpComingFromTouch;
     }
 
-    @Override
-    public boolean isFalsingThresholdNeeded() {
-        return true;
-    }
-
     /**
      * To be called when there's a state change in StatusBarKeyguardViewManager.
      */
@@ -2969,7 +2969,7 @@
 
     private void onLaunchTransitionFadingEnded() {
         mNotificationPanelViewController.resetAlpha();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        mCameraLauncherLazy.get().setLaunchingAffordance(false);
         releaseGestureWakeLock();
         runLaunchTransitionEndRunnable();
         mKeyguardStateController.setLaunchTransitionFadingAway(false);
@@ -3039,7 +3039,7 @@
 
     private void onLaunchTransitionTimeout() {
         Log.w(TAG, "Launch transition: Timeout!");
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        mCameraLauncherLazy.get().setLaunchingAffordance(false);
         releaseGestureWakeLock();
         mNotificationPanelViewController.resetViews(false /* animate */);
     }
@@ -3092,7 +3092,7 @@
         }
         mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
         releaseGestureWakeLock();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        mCameraLauncherLazy.get().setLaunchingAffordance(false);
         mNotificationPanelViewController.resetAlpha();
         mNotificationPanelViewController.resetTranslation();
         mNotificationPanelViewController.resetViewGroupFade();
@@ -3250,7 +3250,7 @@
     @Override
     public void endAffordanceLaunch() {
         releaseGestureWakeLock();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        mCameraLauncherLazy.get().setLaunchingAffordance(false);
     }
 
     /**
@@ -3407,22 +3407,6 @@
         }
     }
 
-    @Override
-    public void onUnlockHintStarted() {
-        mFalsingCollector.onUnlockHintStarted();
-        mKeyguardIndicationController.showActionToUnlock();
-    }
-
-    @Override
-    public void onHintFinished() {
-        // Delay the reset a bit so the user can read the text.
-        mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
-    }
-
-    @Override
-    public void onTrackingStopped(boolean expand) {
-    }
-
     // TODO: Figure out way to remove these.
     @Override
     public NavigationBarView getNavigationBarView() {
@@ -3522,7 +3506,7 @@
     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
         @Override
         public void onFinishedGoingToSleep() {
-            mNotificationPanelViewController.onAffordanceLaunchEnded();
+            mCameraLauncherLazy.get().setLaunchingAffordance(false);
             releaseGestureWakeLock();
             mLaunchCameraWhenFinishedWaking = false;
             mDeviceInteractive = false;
@@ -3623,7 +3607,8 @@
                         .updateSensitivenessForOccludedWakeup();
             }
             if (mLaunchCameraWhenFinishedWaking) {
-                mNotificationPanelViewController.launchCamera(mLastCameraLaunchSource);
+                mCameraLauncherLazy.get().launchCamera(mLastCameraLaunchSource,
+                        mNotificationPanelViewController.isFullyCollapsed());
                 mLaunchCameraWhenFinishedWaking = false;
             }
             if (mLaunchEmergencyActionWhenFinishedWaking) {
@@ -3814,8 +3799,7 @@
 
         mScrimController.setExpansionAffectsAlpha(!unlocking);
 
-        boolean launchingAffordanceWithPreview =
-                mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
+        boolean launchingAffordanceWithPreview = mLaunchingAffordance;
         mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
 
         if (mStatusBarKeyguardViewManager.isShowingAlternateBouncer()) {
@@ -4153,11 +4137,6 @@
 
     // End Extra BaseStatusBarMethods.
 
-    @Override
-    public NotificationGutsManager getGutsManager() {
-        return mGutsManager;
-    }
-
     boolean isTransientShown() {
         return mTransientShown;
     }
@@ -4280,7 +4259,6 @@
             }
             // TODO: Bring these out of CentralSurfaces.
             mUserInfoControllerImpl.onDensityOrFontScaleChanged();
-            mUserSwitcherController.onDensityOrFontScaleChanged();
             mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
             mHeadsUpManager.onDensityOrFontScaleChanged();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index 34cd1ce..7dcdc0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -33,7 +33,7 @@
     private val lastConfig = Configuration()
     private var density: Int = 0
     private var smallestScreenWidth: Int = 0
-    private var maxBounds: Rect? = null
+    private var maxBounds = Rect()
     private var fontScale: Float = 0.toFloat()
     private val inCarMode: Boolean
     private var uiMode: Int = 0
@@ -47,6 +47,7 @@
         fontScale = currentConfig.fontScale
         density = currentConfig.densityDpi
         smallestScreenWidth = currentConfig.smallestScreenWidthDp
+        maxBounds.set(currentConfig.windowConfiguration.maxBounds)
         inCarMode = currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
                 Configuration.UI_MODE_TYPE_CAR
         uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
@@ -92,7 +93,11 @@
 
         val maxBounds = newConfig.windowConfiguration.maxBounds
         if (maxBounds != this.maxBounds) {
-            this.maxBounds = maxBounds
+            // Update our internal rect to have the same bounds, instead of using
+            // `this.maxBounds = maxBounds` directly. Setting it directly means that `maxBounds`
+            // would be a direct reference to windowConfiguration.maxBounds, so the if statement
+            // above would always fail. See b/245799099 for more information.
+            this.maxBounds.set(maxBounds)
             listeners.filterForEach({ this.listeners.contains(it) }) {
                 it.onMaxBoundsChanged()
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 532b8b8..aa0757e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -267,7 +267,7 @@
     private void onFullyShown() {
         mFalsingCollector.onBouncerShown();
         if (mKeyguardViewController == null) {
-            Log.wtf(TAG, "onFullyShown when view was null");
+            Log.e(TAG, "onFullyShown when view was null");
         } else {
             mKeyguardViewController.onResume();
             mContainer.announceForAccessibility(
@@ -279,10 +279,7 @@
      * @see #onFullyShown()
      */
     private void onFullyHidden() {
-        cancelShowRunnable();
-        setVisibility(View.INVISIBLE);
-        mFalsingCollector.onBouncerHidden();
-        DejankUtils.postAfterTraversal(mResetRunnable);
+
     }
 
     private void setVisibility(@View.Visibility int visibility) {
@@ -459,7 +456,13 @@
             onFullyShown();
             dispatchFullyShown();
         } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
-            onFullyHidden();
+            DejankUtils.postAfterTraversal(mResetRunnable);
+            /*
+             * There are cases where #hide() was not invoked, such as when
+             * NotificationPanelViewController controls the hide animation. Make sure the state gets
+             * updated by calling #hide() directly.
+             */
+            hide(false /* destroyView */);
             dispatchFullyHidden();
         } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
             dispatchStartingToHide();
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 18877f9..7a49a49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -26,6 +26,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.util.TypedValue;
@@ -527,4 +528,11 @@
         mClipRect.set(0, mTopClipping, getWidth(), getHeight());
         setClipBounds(mClipRect);
     }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        Trace.beginSection("KeyguardStatusBarView#onMeasure");
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        Trace.endSection();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 8793a57..1d7dfe1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
 import android.app.WallpaperColors;
@@ -45,6 +44,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationMediaManager;
 
 import libcore.io.IoUtils;
@@ -82,10 +82,11 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             DumpManager dumpManager,
             NotificationMediaManager mediaManager,
-            @Main Handler mainHandler) {
+            @Main Handler mainHandler,
+            UserTracker userTracker) {
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
         mWallpaperManager = wallpaperManager;
-        mCurrentUserId = ActivityManager.getCurrentUser();
+        mCurrentUserId = userTracker.getUserId();
         mUpdateMonitor = keyguardUpdateMonitor;
         mMediaManager = mediaManager;
         mH = mainHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
index 94d1bf4..26e6db6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.ActivityManager;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -28,6 +27,7 @@
 
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.settings.UserTracker;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
@@ -44,6 +44,7 @@
 
     private final Context mContext;
     private final UserManager mUserManager;
+    private final UserTracker mUserTracker;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final LinkedList<UserInfo> mProfiles;
     private boolean mListening;
@@ -52,9 +53,11 @@
     /**
      */
     @Inject
-    public ManagedProfileControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher) {
+    public ManagedProfileControllerImpl(Context context, UserTracker userTracker,
+            BroadcastDispatcher broadcastDispatcher) {
         mContext = context;
         mUserManager = UserManager.get(mContext);
+        mUserTracker = userTracker;
         mBroadcastDispatcher = broadcastDispatcher;
         mProfiles = new LinkedList<UserInfo>();
     }
@@ -90,7 +93,7 @@
     private void reloadManagedProfiles() {
         synchronized (mProfiles) {
             boolean hadProfile = mProfiles.size() > 0;
-            int user = ActivityManager.getCurrentUser();
+            int user = mUserTracker.getUserId();
             mProfiles.clear();
 
             for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
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 86e27ab..c527f30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -53,7 +53,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -205,7 +204,6 @@
     private final ScreenOffAnimationController mScreenOffAnimationController;
     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    private KeyguardViewMediator mKeyguardViewMediator;
 
     private GradientColors mColors;
     private boolean mNeedsDrawableColorUpdate;
@@ -275,8 +273,7 @@
             @Main Executor mainExecutor,
             ScreenOffAnimationController screenOffAnimationController,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
-            KeyguardViewMediator keyguardViewMediator) {
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
         mScrimStateListener = lightBarController::setScrimState;
         mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
 
@@ -315,8 +312,6 @@
             }
         });
         mColors = new GradientColors();
-
-        mKeyguardViewMediator = keyguardViewMediator;
     }
 
     /**
@@ -812,13 +807,6 @@
                         mBehindTint,
                         interpolatedFraction);
             }
-
-            // If we're unlocked but still playing the occlude animation, remain at the keyguard
-            // alpha temporarily.
-            if (mKeyguardViewMediator.isOccludeAnimationPlaying()
-                    || mState.mLaunchingAffordanceWithPreview) {
-                mNotificationsAlpha = KEYGUARD_SCRIM_ALPHA;
-            }
         } else if (mState == ScrimState.AUTH_SCRIMMED_SHADE) {
             mNotificationsAlpha = (float) Math.pow(getInterpolatedFraction(), 0.8f);
         } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
@@ -895,7 +883,7 @@
 
         float stateBehind = mClipsQsScrim ? state.getNotifAlpha() : state.getBehindAlpha();
         float behindAlpha;
-        int behindTint;
+        int behindTint = state.getBehindTint();
         if (mDarkenWhileDragging) {
             behindAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
                     interpolatedFract);
@@ -903,12 +891,14 @@
             behindAlpha = MathUtils.lerp(0 /* start */, stateBehind,
                     interpolatedFract);
         }
-        if (mClipsQsScrim) {
-            behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
+        if (mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()) {
+            if (mClipsQsScrim) {
+                behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
                     state.getNotifTint(), interpolatedFract);
-        } else {
-            behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+            } else {
+                behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
                     state.getBehindTint(), interpolatedFract);
+            }
         }
         if (mQsExpansion > 0) {
             behindAlpha = MathUtils.lerp(behindAlpha, mDefaultScrimAlpha, mQsExpansion);
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 56fb337..01a1ebe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -165,6 +165,7 @@
             @Override
             public void onFullyHidden() {
                 mPrimaryBouncerAnimating = false;
+                updateStates();
             }
 
             @Override
@@ -468,7 +469,7 @@
             // Don't expand to the bouncer. Instead transition back to the lock screen (see
             // CentralSurfaces#showBouncerOrLockScreenIfKeyguard)
             return;
-        } else if (primaryBouncerNeedsScrimming()) {
+        } else if (needsFullscreenBouncer()) {
             if (mPrimaryBouncer != null) {
                 mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
             } else {
@@ -1184,12 +1185,16 @@
             updateNavigationBarVisibility(navBarVisible);
         }
 
-        if (primaryBouncerShowing != mLastPrimaryBouncerShowing || mFirstUpdate) {
+        boolean isPrimaryBouncerShowingChanged =
+            primaryBouncerShowing != mLastPrimaryBouncerShowing;
+        mLastPrimaryBouncerShowing = primaryBouncerShowing;
+
+        if (isPrimaryBouncerShowingChanged || mFirstUpdate) {
             mNotificationShadeWindowController.setBouncerShowing(primaryBouncerShowing);
             mCentralSurfaces.setBouncerShowing(primaryBouncerShowing);
         }
         if (primaryBouncerIsOrWillBeShowing != mLastPrimaryBouncerIsOrWillBeShowing || mFirstUpdate
-                || primaryBouncerShowing != mLastPrimaryBouncerShowing) {
+                || isPrimaryBouncerShowingChanged) {
             mKeyguardUpdateManager.sendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing,
                     primaryBouncerShowing);
         }
@@ -1198,7 +1203,6 @@
         mLastShowing = showing;
         mLastGlobalActionsVisible = mGlobalActionsVisible;
         mLastOccluded = occluded;
-        mLastPrimaryBouncerShowing = primaryBouncerShowing;
         mLastPrimaryBouncerIsOrWillBeShowing = primaryBouncerIsOrWillBeShowing;
         mLastBouncerDismissible = primaryBouncerDismissible;
         mLastRemoteInputActive = remoteInputActive;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index dc90266..206c0aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -28,13 +28,13 @@
 import com.android.systemui.battery.BatteryMeterView;
 import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.biometrics.AuthRippleView;
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.privacy.OngoingPrivacyChip;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.CombinedShadeHeadersConstraintManager;
 import com.android.systemui.shade.CombinedShadeHeadersConstraintManagerImpl;
 import com.android.systemui.shade.NotificationPanelView;
@@ -221,20 +221,22 @@
     @Named(LARGE_SCREEN_BATTERY_CONTROLLER)
     static BatteryMeterViewController getBatteryMeterViewController(
             @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView,
+            UserTracker userTracker,
             ConfigurationController configurationController,
             TunerService tunerService,
-            BroadcastDispatcher broadcastDispatcher,
             @Main Handler mainHandler,
             ContentResolver contentResolver,
+            FeatureFlags featureFlags,
             BatteryController batteryController
     ) {
         return new BatteryMeterViewController(
                 batteryMeterView,
+                userTracker,
                 configurationController,
                 tunerService,
-                broadcastDispatcher,
                 mainHandler,
                 contentResolver,
+                featureFlags,
                 batteryController);
 
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt
index 60bd038..501467f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt
@@ -32,6 +32,7 @@
 interface MobileMappingsProxy {
     fun mapIconSets(config: Config): Map<String, MobileIconGroup>
     fun getDefaultIcons(config: Config): MobileIconGroup
+    fun getIconKey(displayInfo: TelephonyDisplayInfo): String
     fun toIconKey(@NetworkType networkType: Int): String
     fun toIconKeyOverride(@NetworkType networkType: Int): String
 }
@@ -44,6 +45,9 @@
     override fun getDefaultIcons(config: Config): MobileIconGroup =
         MobileMappings.getDefaultIcons(config)
 
+    override fun getIconKey(displayInfo: TelephonyDisplayInfo): String =
+        MobileMappings.getIconKey(displayInfo)
+
     override fun toIconKey(@NetworkType networkType: Int): String =
         MobileMappings.toIconKey(networkType)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
index cf4106c..68d30d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
@@ -21,7 +21,6 @@
 import android.graphics.ColorMatrix
 import android.graphics.ColorMatrixColorFilter
 import android.graphics.drawable.Drawable
-import android.os.UserHandle
 import android.widget.BaseAdapter
 import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower
 import com.android.systemui.user.data.source.UserRecord
@@ -84,7 +83,7 @@
     }
 
     fun refresh() {
-        controller.refreshUsers(UserHandle.USER_NULL)
+        controller.refreshUsers()
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 149ed0a..d10d7cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -155,6 +155,9 @@
 
         default void onWirelessChargingChanged(boolean isWirlessCharging) {
         }
+
+        default void onIsOverheatedChanged(boolean isOverheated) {
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index c7ad767..2ee5232 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.os.BatteryManager.BATTERY_HEALTH_OVERHEAT;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_HEALTH;
 import static android.os.BatteryManager.EXTRA_PRESENT;
 
 import android.annotation.WorkerThread;
@@ -87,6 +90,7 @@
     protected boolean mPowerSave;
     private boolean mAodPowerSave;
     private boolean mWirelessCharging;
+    private boolean mIsOverheated = false;
     private boolean mTestMode = false;
     @VisibleForTesting
     boolean mHasReceivedBattery = false;
@@ -152,6 +156,7 @@
         pw.print("  mPluggedIn="); pw.println(mPluggedIn);
         pw.print("  mCharging="); pw.println(mCharging);
         pw.print("  mCharged="); pw.println(mCharged);
+        pw.print("  mIsOverheated="); pw.println(mIsOverheated);
         pw.print("  mPowerSave="); pw.println(mPowerSave);
         pw.print("  mStateUnknown="); pw.println(mStateUnknown);
     }
@@ -184,6 +189,7 @@
         cb.onPowerSaveChanged(mPowerSave);
         cb.onBatteryUnknownStateChanged(mStateUnknown);
         cb.onWirelessChargingChanged(mWirelessCharging);
+        cb.onIsOverheatedChanged(mIsOverheated);
     }
 
     @Override
@@ -222,6 +228,13 @@
                 fireBatteryUnknownStateChanged();
             }
 
+            int batteryHealth = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
+            boolean isOverheated = batteryHealth == BATTERY_HEALTH_OVERHEAT;
+            if (isOverheated != mIsOverheated) {
+                mIsOverheated = isOverheated;
+                fireIsOverheatedChanged();
+            }
+
             fireBatteryLevelChanged();
         } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
             updatePowerSave();
@@ -292,6 +305,10 @@
         return mPluggedChargingSource == BatteryManager.BATTERY_PLUGGED_WIRELESS;
     }
 
+    public boolean isOverheated() {
+        return mIsOverheated;
+    }
+
     @Override
     public void getEstimatedTimeRemainingString(EstimateFetchCompletion completion) {
         // Need to fetch or refresh the estimate, but it may involve binder calls so offload the
@@ -402,6 +419,15 @@
         }
     }
 
+    private void fireIsOverheatedChanged() {
+        synchronized (mChangeCallbacks) {
+            final int n = mChangeCallbacks.size();
+            for (int i = 0; i < n; i++) {
+                mChangeCallbacks.get(i).onIsOverheatedChanged(mIsOverheated);
+            }
+        }
+    }
+
     @Override
     public void dispatchDemoCommand(String command, Bundle args) {
         if (!mDemoModeController.isInDemoMode()) {
@@ -412,6 +438,7 @@
         String plugged = args.getString("plugged");
         String powerSave = args.getString("powersave");
         String present = args.getString("present");
+        String overheated = args.getString("overheated");
         if (level != null) {
             mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
         }
@@ -426,6 +453,10 @@
             mStateUnknown = !present.equals("true");
             fireBatteryUnknownStateChanged();
         }
+        if (overheated != null) {
+            mIsOverheated = overheated.equals("true");
+            fireIsOverheatedChanged();
+        }
         fireBatteryLevelChanged();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index aae0f93..38b3769 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.policy;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
@@ -41,6 +40,7 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -83,6 +83,7 @@
     @Inject
     public BluetoothControllerImpl(
             Context context,
+            UserTracker userTracker,
             DumpManager dumpManager,
             BluetoothLogger logger,
             @Background Looper bgLooper,
@@ -100,7 +101,7 @@
                     mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
         }
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-        mCurrentUser = ActivityManager.getCurrentUser();
+        mCurrentUser = userTracker.getUserId();
         mDumpManager.registerDumpable(TAG, this);
     }
 
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 576962d..d84cbcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.annotation.NonNull;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -49,7 +50,7 @@
 import com.android.systemui.demomode.DemoModeCommandReceiver;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -79,7 +80,7 @@
     private static final String SHOW_SECONDS = "show_seconds";
     private static final String VISIBILITY = "visibility";
 
-    private final CurrentUserTracker mCurrentUserTracker;
+    private final UserTracker mUserTracker;
     private final CommandQueue mCommandQueue;
     private int mCurrentUserId;
 
@@ -114,6 +115,14 @@
 
     private final BroadcastDispatcher mBroadcastDispatcher;
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    mCurrentUserId = newUser;
+                }
+            };
+
     public Clock(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -132,12 +141,7 @@
             a.recycle();
         }
         mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
-        mCurrentUserTracker = new CurrentUserTracker(mBroadcastDispatcher) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                mCurrentUserId = newUserId;
-            }
-        };
+        mUserTracker = Dependency.get(UserTracker.class);
     }
 
     @Override
@@ -196,8 +200,8 @@
             Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
                     StatusBarIconController.ICON_HIDE_LIST);
             mCommandQueue.addCallback(this);
-            mCurrentUserTracker.startTracking();
-            mCurrentUserId = mCurrentUserTracker.getCurrentUserId();
+            mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());
+            mCurrentUserId = mUserTracker.getUserId();
         }
 
         // The time zone may have changed while the receiver wasn't registered, so update the Time
@@ -227,7 +231,7 @@
             mAttached = false;
             Dependency.get(TunerService.class).removeTunable(this);
             mCommandQueue.removeCallback(this);
-            mCurrentUserTracker.stopTracking();
+            mUserTracker.removeCallback(mUserChangedCallback);
         }
     }
 
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 69b55c8..a4821e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -18,7 +18,6 @@
 
 import static android.net.TetheringManager.TETHERING_WIFI;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.TetheringManager;
@@ -38,6 +37,7 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -59,6 +59,7 @@
     private final WifiManager mWifiManager;
     private final Handler mMainHandler;
     private final Context mContext;
+    private final UserTracker mUserTracker;
 
     private int mHotspotState;
     private volatile int mNumConnectedDevices;
@@ -95,10 +96,12 @@
     @Inject
     public HotspotControllerImpl(
             Context context,
+            UserTracker userTracker,
             @Main Handler mainHandler,
             @Background Handler backgroundHandler,
             DumpManager dumpManager) {
         mContext = context;
+        mUserTracker = userTracker;
         mTetheringManager = context.getSystemService(TetheringManager.class);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         mMainHandler = mainHandler;
@@ -125,7 +128,7 @@
     @Override
     public boolean isHotspotSupported() {
         return mIsTetheringSupportedConfig && mIsTetheringSupported && mHasTetherableWifiRegexs
-                && UserManager.get(mContext).isUserAdmin(ActivityManager.getCurrentUser());
+                && UserManager.get(mContext).isUserAdmin(mUserTracker.getUserId());
     }
 
     public void dump(PrintWriter pw, String[] args) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index cc241d9..ba94714 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -16,7 +16,6 @@
 package com.android.systemui.statusbar.policy;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManager.DeviceOwnerType;
@@ -55,8 +54,9 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 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.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -70,7 +70,7 @@
 /**
  */
 @SysUISingleton
-public class SecurityControllerImpl extends CurrentUserTracker implements SecurityController {
+public class SecurityControllerImpl implements SecurityController {
 
     private static final String TAG = "SecurityController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -84,11 +84,13 @@
     private static final int CA_CERT_LOADING_RETRY_TIME_IN_MS = 30_000;
 
     private final Context mContext;
+    private final UserTracker mUserTracker;
     private final ConnectivityManager mConnectivityManager;
     private final VpnManager mVpnManager;
     private final DevicePolicyManager mDevicePolicyManager;
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
+    private final Executor mMainExecutor;
     private final Executor mBgExecutor;
 
     @GuardedBy("mCallbacks")
@@ -102,18 +104,28 @@
     // Needs to be cached here since the query has to be asynchronous
     private ArrayMap<Integer, Boolean> mHasCACerts = new ArrayMap<Integer, Boolean>();
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    onUserSwitched(newUser);
+                }
+            };
+
     /**
      */
     @Inject
     public SecurityControllerImpl(
             Context context,
+            UserTracker userTracker,
             @Background Handler bgHandler,
             BroadcastDispatcher broadcastDispatcher,
+            @Main Executor mainExecutor,
             @Background Executor bgExecutor,
             DumpManager dumpManager
     ) {
-        super(broadcastDispatcher);
         mContext = context;
+        mUserTracker = userTracker;
         mDevicePolicyManager = (DevicePolicyManager)
                 context.getSystemService(Context.DEVICE_POLICY_SERVICE);
         mConnectivityManager = (ConnectivityManager)
@@ -121,6 +133,7 @@
         mVpnManager = context.getSystemService(VpnManager.class);
         mPackageManager = context.getPackageManager();
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mMainExecutor = mainExecutor;
         mBgExecutor = bgExecutor;
 
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
@@ -133,8 +146,8 @@
 
         // TODO: re-register network callback on user change.
         mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
-        onUserSwitched(ActivityManager.getCurrentUser());
-        startTracking();
+        onUserSwitched(mUserTracker.getUserId());
+        mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
     }
 
     public void dump(PrintWriter pw, String[] args) {
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 29285f8..a593d51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,7 +27,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.ContactsContract;
@@ -40,8 +38,11 @@
 import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
 
 import java.util.ArrayList;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -53,6 +54,7 @@
     private static final String TAG = "UserInfoController";
 
     private final Context mContext;
+    private final UserTracker mUserTracker;
     private final ArrayList<OnUserInfoChangedListener> mCallbacks =
             new ArrayList<OnUserInfoChangedListener>();
     private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
@@ -64,11 +66,11 @@
     /**
      */
     @Inject
-    public UserInfoControllerImpl(Context context) {
+    public UserInfoControllerImpl(Context context, @Main Executor mainExecutor,
+            UserTracker userTracker) {
         mContext = context;
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_USER_SWITCHED);
-        mContext.registerReceiver(mReceiver, filter);
+        mUserTracker = userTracker;
+        mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
 
         IntentFilter profileFilter = new IntentFilter();
         profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
@@ -88,15 +90,13 @@
         mCallbacks.remove(callback);
     }
 
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                reloadUserInfo();
-            }
-        }
-    };
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, @NonNull Context userContext) {
+                    reloadUserInfo();
+                }
+            };
 
     private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
         @Override
@@ -104,15 +104,11 @@
             final String action = intent.getAction();
             if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
                     Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
-                try {
-                    final int currentUser = ActivityManager.getService().getCurrentUser().id;
-                    final int changedUser =
-                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
-                    if (changedUser == currentUser) {
-                        reloadUserInfo();
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Couldn't get current user id for profile change", e);
+                final int currentUser = mUserTracker.getUserId();
+                final int changedUser =
+                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
+                if (changedUser == currentUser) {
+                    reloadUserInfo();
                 }
             }
         }
@@ -130,15 +126,12 @@
         Context currentUserContext;
         UserInfo userInfo;
         try {
-            userInfo = ActivityManager.getService().getCurrentUser();
+            userInfo = mUserTracker.getUserInfo();
             currentUserContext = mContext.createPackageContextAsUser("android", 0,
                     new UserHandle(userInfo.id));
         } catch (PackageManager.NameNotFoundException e) {
             Log.e(TAG, "Couldn't create user context", e);
             throw new RuntimeException(e);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't get user info", e);
-            throw new RuntimeException(e);
         }
         final int userId = userInfo.id;
         final boolean isGuest = userInfo.isGuest();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index 146b222..bdb656b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -14,35 +14,74 @@
  * limitations under the License.
  *
  */
+
 package com.android.systemui.statusbar.policy
 
-import android.annotation.UserIdInt
+import android.content.Context
 import android.content.Intent
 import android.view.View
-import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower
 import com.android.systemui.user.data.source.UserRecord
+import com.android.systemui.user.domain.interactor.GuestUserInteractor
+import com.android.systemui.user.domain.interactor.UserInteractor
 import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
+import dagger.Lazy
+import java.io.PrintWriter
 import java.lang.ref.WeakReference
-import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
 
-/** Defines interface for a class that provides user switching functionality and state. */
-interface UserSwitcherController : Dumpable {
+/** Access point into multi-user switching logic. */
+@Deprecated("Use UserInteractor or GuestUserInteractor instead.")
+@SysUISingleton
+class UserSwitcherController
+@Inject
+constructor(
+    @Application private val applicationContext: Context,
+    private val userInteractorLazy: Lazy<UserInteractor>,
+    private val guestUserInteractorLazy: Lazy<GuestUserInteractor>,
+    private val keyguardInteractorLazy: Lazy<KeyguardInteractor>,
+    private val activityStarter: ActivityStarter,
+) {
+
+    /** Defines interface for classes that can be called back when the user is switched. */
+    fun interface UserSwitchCallback {
+        /** Notifies that the user has switched. */
+        fun onUserSwitched()
+    }
+
+    private val userInteractor: UserInteractor by lazy { userInteractorLazy.get() }
+    private val guestUserInteractor: GuestUserInteractor by lazy { guestUserInteractorLazy.get() }
+    private val keyguardInteractor: KeyguardInteractor by lazy { keyguardInteractorLazy.get() }
+
+    private val callbackCompatMap = mutableMapOf<UserSwitchCallback, UserInteractor.UserCallback>()
 
     /** The current list of [UserRecord]. */
     val users: ArrayList<UserRecord>
+        get() = userInteractor.userRecords.value
 
     /** Whether the user switcher experience should use the simple experience. */
     val isSimpleUserSwitcher: Boolean
-
-    /** Require a view for jank detection */
-    fun init(view: View)
+        get() = userInteractor.isSimpleUserSwitcher
 
     /** The [UserRecord] of the current user or `null` when none. */
     val currentUserRecord: UserRecord?
+        get() = userInteractor.selectedUserRecord.value
 
     /** The name of the current user of the device or `null`, when none is selected. */
     val currentUserName: String?
+        get() =
+            currentUserRecord?.let {
+                LegacyUserUiHelper.getUserRecordName(
+                    context = applicationContext,
+                    record = it,
+                    isGuestUserAutoCreated = userInteractor.isGuestUserAutoCreated,
+                    isGuestUserResetting = userInteractor.isGuestUserResetting,
+                )
+            }
 
     /**
      * Notifies that a user has been selected.
@@ -55,34 +94,40 @@
      * @param userId The ID of the user to switch to.
      * @param dialogShower An optional [DialogShower] in case we need to show dialogs.
      */
-    fun onUserSelected(userId: Int, dialogShower: DialogShower?)
-
-    /** Whether it is allowed to add users while the device is locked. */
-    val isAddUsersFromLockScreenEnabled: Flow<Boolean>
+    fun onUserSelected(userId: Int, dialogShower: DialogShower?) {
+        userInteractor.selectUser(userId, dialogShower)
+    }
 
     /** Whether the guest user is configured to always be present on the device. */
     val isGuestUserAutoCreated: Boolean
+        get() = userInteractor.isGuestUserAutoCreated
 
     /** Whether the guest user is currently being reset. */
     val isGuestUserResetting: Boolean
-
-    /** Creates and switches to the guest user. */
-    fun createAndSwitchToGuestUser(dialogShower: DialogShower?)
-
-    /** Shows the add user dialog. */
-    fun showAddUserDialog(dialogShower: DialogShower?)
-
-    /** Starts an activity to add a supervised user to the device. */
-    fun startSupervisedUserActivity()
-
-    /** Notifies when the display density or font scale has changed. */
-    fun onDensityOrFontScaleChanged()
+        get() = userInteractor.isGuestUserResetting
 
     /** Registers an adapter to notify when the users change. */
-    fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>)
+    fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>) {
+        userInteractor.addCallback(
+            object : UserInteractor.UserCallback {
+                override fun isEvictable(): Boolean {
+                    return adapter.get() == null
+                }
+
+                override fun onUserStateChanged() {
+                    adapter.get()?.notifyDataSetChanged()
+                }
+            }
+        )
+    }
 
     /** Notifies the item for a user has been clicked. */
-    fun onUserListItemClicked(record: UserRecord, dialogShower: DialogShower?)
+    fun onUserListItemClicked(
+        record: UserRecord,
+        dialogShower: DialogShower?,
+    ) {
+        userInteractor.onRecordSelected(record, dialogShower)
+    }
 
     /**
      * Removes guest user and switches to target user. The guest must be the current user and its id
@@ -103,7 +148,12 @@
      * @param targetUserId id of the user to switch to after guest is removed. If
      * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
      */
-    fun removeGuestUser(@UserIdInt guestUserId: Int, @UserIdInt targetUserId: Int)
+    fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
+        userInteractor.removeGuestUser(
+            guestUserId = guestUserId,
+            targetUserId = targetUserId,
+        )
+    }
 
     /**
      * Exits guest user and switches to previous non-guest user. The guest must be the current user.
@@ -114,43 +164,58 @@
      * @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
      * only if its ephemeral, else keep guest
      */
-    fun exitGuestUser(
-        @UserIdInt guestUserId: Int,
-        @UserIdInt targetUserId: Int,
-        forceRemoveGuestOnExit: Boolean
-    )
+    fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
+        userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
+    }
 
     /**
      * Guarantee guest is present only if the device is provisioned. Otherwise, create a content
      * observer to wait until the device is provisioned, then schedule the guest creation.
      */
-    fun schedulePostBootGuestCreation()
+    fun schedulePostBootGuestCreation() {
+        guestUserInteractor.onDeviceBootCompleted()
+    }
 
     /** Whether keyguard is showing. */
     val isKeyguardShowing: Boolean
+        get() = keyguardInteractor.isKeyguardShowing()
 
     /** Starts an activity with the given [Intent]. */
-    fun startActivity(intent: Intent)
+    fun startActivity(intent: Intent) {
+        activityStarter.startActivity(intent, /* dismissShade= */ true)
+    }
 
     /**
      * Refreshes users from UserManager.
      *
      * The pictures are only loaded if they have not been loaded yet.
-     *
-     * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
      */
-    fun refreshUsers(forcePictureLoadForId: Int)
+    fun refreshUsers() {
+        userInteractor.refreshUsers()
+    }
 
     /** Adds a subscriber to when user switches. */
-    fun addUserSwitchCallback(callback: UserSwitchCallback)
+    fun addUserSwitchCallback(callback: UserSwitchCallback) {
+        val interactorCallback =
+            object : UserInteractor.UserCallback {
+                override fun onUserStateChanged() {
+                    callback.onUserSwitched()
+                }
+            }
+        callbackCompatMap[callback] = interactorCallback
+        userInteractor.addCallback(interactorCallback)
+    }
 
     /** Removes a previously-added subscriber. */
-    fun removeUserSwitchCallback(callback: UserSwitchCallback)
+    fun removeUserSwitchCallback(callback: UserSwitchCallback) {
+        val interactorCallback = callbackCompatMap.remove(callback)
+        if (interactorCallback != null) {
+            userInteractor.removeCallback(interactorCallback)
+        }
+    }
 
-    /** Defines interface for classes that can be called back when the user is switched. */
-    fun interface UserSwitchCallback {
-        /** Notifies that the user has switched. */
-        fun onUserSwitched()
+    fun dump(pw: PrintWriter, args: Array<out String>) {
+        userInteractor.dump(pw)
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt
deleted file mode 100644
index 935fc7f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerImpl.kt
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.statusbar.policy
-
-import android.content.Context
-import android.content.Intent
-import android.view.View
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.user.domain.interactor.GuestUserInteractor
-import com.android.systemui.user.domain.interactor.UserInteractor
-import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
-import dagger.Lazy
-import java.io.PrintWriter
-import java.lang.ref.WeakReference
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-
-/** Implementation of [UserSwitcherController]. */
-@SysUISingleton
-class UserSwitcherControllerImpl
-@Inject
-constructor(
-    @Application private val applicationContext: Context,
-    flags: FeatureFlags,
-    @Suppress("DEPRECATION") private val oldImpl: Lazy<UserSwitcherControllerOldImpl>,
-    private val userInteractorLazy: Lazy<UserInteractor>,
-    private val guestUserInteractorLazy: Lazy<GuestUserInteractor>,
-    private val keyguardInteractorLazy: Lazy<KeyguardInteractor>,
-    private val activityStarter: ActivityStarter,
-) : UserSwitcherController {
-
-    private val useInteractor: Boolean =
-        flags.isEnabled(Flags.USER_CONTROLLER_USES_INTERACTOR) &&
-            !flags.isEnabled(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER)
-    private val _oldImpl: UserSwitcherControllerOldImpl
-        get() = oldImpl.get()
-    private val userInteractor: UserInteractor by lazy { userInteractorLazy.get() }
-    private val guestUserInteractor: GuestUserInteractor by lazy { guestUserInteractorLazy.get() }
-    private val keyguardInteractor: KeyguardInteractor by lazy { keyguardInteractorLazy.get() }
-
-    private val callbackCompatMap =
-        mutableMapOf<UserSwitcherController.UserSwitchCallback, UserInteractor.UserCallback>()
-
-    private fun notSupported(): Nothing {
-        error("Not supported in the new implementation!")
-    }
-
-    override val users: ArrayList<UserRecord>
-        get() =
-            if (useInteractor) {
-                userInteractor.userRecords.value
-            } else {
-                _oldImpl.users
-            }
-
-    override val isSimpleUserSwitcher: Boolean
-        get() =
-            if (useInteractor) {
-                userInteractor.isSimpleUserSwitcher
-            } else {
-                _oldImpl.isSimpleUserSwitcher
-            }
-
-    override fun init(view: View) {
-        if (!useInteractor) {
-            _oldImpl.init(view)
-        }
-    }
-
-    override val currentUserRecord: UserRecord?
-        get() =
-            if (useInteractor) {
-                userInteractor.selectedUserRecord.value
-            } else {
-                _oldImpl.currentUserRecord
-            }
-
-    override val currentUserName: String?
-        get() =
-            if (useInteractor) {
-                currentUserRecord?.let {
-                    LegacyUserUiHelper.getUserRecordName(
-                        context = applicationContext,
-                        record = it,
-                        isGuestUserAutoCreated = userInteractor.isGuestUserAutoCreated,
-                        isGuestUserResetting = userInteractor.isGuestUserResetting,
-                    )
-                }
-            } else {
-                _oldImpl.currentUserName
-            }
-
-    override fun onUserSelected(
-        userId: Int,
-        dialogShower: UserSwitchDialogController.DialogShower?
-    ) {
-        if (useInteractor) {
-            userInteractor.selectUser(userId, dialogShower)
-        } else {
-            _oldImpl.onUserSelected(userId, dialogShower)
-        }
-    }
-
-    override val isAddUsersFromLockScreenEnabled: Flow<Boolean>
-        get() =
-            if (useInteractor) {
-                notSupported()
-            } else {
-                _oldImpl.isAddUsersFromLockScreenEnabled
-            }
-
-    override val isGuestUserAutoCreated: Boolean
-        get() =
-            if (useInteractor) {
-                userInteractor.isGuestUserAutoCreated
-            } else {
-                _oldImpl.isGuestUserAutoCreated
-            }
-
-    override val isGuestUserResetting: Boolean
-        get() =
-            if (useInteractor) {
-                userInteractor.isGuestUserResetting
-            } else {
-                _oldImpl.isGuestUserResetting
-            }
-
-    override fun createAndSwitchToGuestUser(
-        dialogShower: UserSwitchDialogController.DialogShower?,
-    ) {
-        if (useInteractor) {
-            notSupported()
-        } else {
-            _oldImpl.createAndSwitchToGuestUser(dialogShower)
-        }
-    }
-
-    override fun showAddUserDialog(dialogShower: UserSwitchDialogController.DialogShower?) {
-        if (useInteractor) {
-            notSupported()
-        } else {
-            _oldImpl.showAddUserDialog(dialogShower)
-        }
-    }
-
-    override fun startSupervisedUserActivity() {
-        if (useInteractor) {
-            notSupported()
-        } else {
-            _oldImpl.startSupervisedUserActivity()
-        }
-    }
-
-    override fun onDensityOrFontScaleChanged() {
-        if (!useInteractor) {
-            _oldImpl.onDensityOrFontScaleChanged()
-        }
-    }
-
-    override fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>) {
-        if (useInteractor) {
-            userInteractor.addCallback(
-                object : UserInteractor.UserCallback {
-                    override fun isEvictable(): Boolean {
-                        return adapter.get() == null
-                    }
-
-                    override fun onUserStateChanged() {
-                        adapter.get()?.notifyDataSetChanged()
-                    }
-                }
-            )
-        } else {
-            _oldImpl.addAdapter(adapter)
-        }
-    }
-
-    override fun onUserListItemClicked(
-        record: UserRecord,
-        dialogShower: UserSwitchDialogController.DialogShower?,
-    ) {
-        if (useInteractor) {
-            userInteractor.onRecordSelected(record, dialogShower)
-        } else {
-            _oldImpl.onUserListItemClicked(record, dialogShower)
-        }
-    }
-
-    override fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
-        if (useInteractor) {
-            userInteractor.removeGuestUser(
-                guestUserId = guestUserId,
-                targetUserId = targetUserId,
-            )
-        } else {
-            _oldImpl.removeGuestUser(guestUserId, targetUserId)
-        }
-    }
-
-    override fun exitGuestUser(
-        guestUserId: Int,
-        targetUserId: Int,
-        forceRemoveGuestOnExit: Boolean
-    ) {
-        if (useInteractor) {
-            userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
-        } else {
-            _oldImpl.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
-        }
-    }
-
-    override fun schedulePostBootGuestCreation() {
-        if (useInteractor) {
-            guestUserInteractor.onDeviceBootCompleted()
-        } else {
-            _oldImpl.schedulePostBootGuestCreation()
-        }
-    }
-
-    override val isKeyguardShowing: Boolean
-        get() =
-            if (useInteractor) {
-                keyguardInteractor.isKeyguardShowing()
-            } else {
-                _oldImpl.isKeyguardShowing
-            }
-
-    override fun startActivity(intent: Intent) {
-        if (useInteractor) {
-            activityStarter.startActivity(intent, /* dismissShade= */ true)
-        } else {
-            _oldImpl.startActivity(intent)
-        }
-    }
-
-    override fun refreshUsers(forcePictureLoadForId: Int) {
-        if (useInteractor) {
-            userInteractor.refreshUsers()
-        } else {
-            _oldImpl.refreshUsers(forcePictureLoadForId)
-        }
-    }
-
-    override fun addUserSwitchCallback(callback: UserSwitcherController.UserSwitchCallback) {
-        if (useInteractor) {
-            val interactorCallback =
-                object : UserInteractor.UserCallback {
-                    override fun onUserStateChanged() {
-                        callback.onUserSwitched()
-                    }
-                }
-            callbackCompatMap[callback] = interactorCallback
-            userInteractor.addCallback(interactorCallback)
-        } else {
-            _oldImpl.addUserSwitchCallback(callback)
-        }
-    }
-
-    override fun removeUserSwitchCallback(callback: UserSwitcherController.UserSwitchCallback) {
-        if (useInteractor) {
-            val interactorCallback = callbackCompatMap.remove(callback)
-            if (interactorCallback != null) {
-                userInteractor.removeCallback(interactorCallback)
-            }
-        } else {
-            _oldImpl.removeUserSwitchCallback(callback)
-        }
-    }
-
-    override fun dump(pw: PrintWriter, args: Array<out String>) {
-        if (useInteractor) {
-            userInteractor.dump(pw)
-        } else {
-            _oldImpl.dump(pw, args)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImpl.java
deleted file mode 100644
index c294c37..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImpl.java
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.policy;
-
-import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
-
-import android.annotation.UserIdInt;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.IActivityManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.telephony.TelephonyCallback;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.view.WindowManagerGlobal;
-import android.widget.Toast;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.settingslib.users.UserCreatingDialog;
-import com.android.systemui.GuestResetOrExitSessionReceiver;
-import com.android.systemui.GuestResumeSessionReceiver;
-import com.android.systemui.SystemUISecondaryUserService;
-import com.android.systemui.animation.DialogCuj;
-import com.android.systemui.animation.DialogLaunchAnimator;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.broadcast.BroadcastSender;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.LongRunning;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.qs.QSUserSwitcherEvent;
-import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.telephony.TelephonyListenerManager;
-import com.android.systemui.user.data.source.UserRecord;
-import com.android.systemui.user.legacyhelper.data.LegacyUserDataHelper;
-import com.android.systemui.user.shared.model.UserActionModel;
-import com.android.systemui.user.ui.dialog.AddUserDialog;
-import com.android.systemui.user.ui.dialog.ExitGuestDialog;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SecureSettings;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-import javax.inject.Inject;
-
-import kotlinx.coroutines.flow.Flow;
-import kotlinx.coroutines.flow.MutableStateFlow;
-import kotlinx.coroutines.flow.StateFlowKt;
-
-/**
- * Old implementation. Keeps a list of all users on the device for user switching.
- *
- * @deprecated This is the old implementation. Please depend on {@link UserSwitcherController}
- * instead.
- */
-@Deprecated
-@SysUISingleton
-public class UserSwitcherControllerOldImpl implements UserSwitcherController {
-
-    private static final String TAG = "UserSwitcherController";
-    private static final boolean DEBUG = false;
-    private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
-            "lockscreenSimpleUserSwitcher";
-    private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
-
-    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
-    private static final long MULTI_USER_JOURNEY_TIMEOUT = 20000L;
-
-    private static final String INTERACTION_JANK_ADD_NEW_USER_TAG = "add_new_user";
-    private static final String INTERACTION_JANK_EXIT_GUEST_MODE_TAG = "exit_guest_mode";
-
-    protected final Context mContext;
-    protected final UserTracker mUserTracker;
-    protected final UserManager mUserManager;
-    private final ContentObserver mSettingsObserver;
-    private final ArrayList<WeakReference<BaseUserSwitcherAdapter>> mAdapters = new ArrayList<>();
-    @VisibleForTesting
-    final GuestResumeSessionReceiver mGuestResumeSessionReceiver;
-    @VisibleForTesting
-    final GuestResetOrExitSessionReceiver mGuestResetOrExitSessionReceiver;
-    private final KeyguardStateController mKeyguardStateController;
-    private final DeviceProvisionedController mDeviceProvisionedController;
-    private final DevicePolicyManager mDevicePolicyManager;
-    protected final Handler mHandler;
-    private final ActivityStarter mActivityStarter;
-    private final BroadcastDispatcher mBroadcastDispatcher;
-    private final BroadcastSender mBroadcastSender;
-    private final TelephonyListenerManager mTelephonyListenerManager;
-    private final InteractionJankMonitor mInteractionJankMonitor;
-    private final LatencyTracker mLatencyTracker;
-    private final DialogLaunchAnimator mDialogLaunchAnimator;
-
-    private ArrayList<UserRecord> mUsers = new ArrayList<>();
-    @VisibleForTesting
-    AlertDialog mExitGuestDialog;
-    @VisibleForTesting
-    Dialog mAddUserDialog;
-    private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
-    private boolean mSimpleUserSwitcher;
-    // When false, there won't be any visual affordance to add a new user from the keyguard even if
-    // the user is unlocked
-    private final MutableStateFlow<Boolean> mAddUsersFromLockScreen =
-            StateFlowKt.MutableStateFlow(false);
-    private boolean mUserSwitcherEnabled;
-    @VisibleForTesting
-    boolean mPauseRefreshUsers;
-    private int mSecondaryUser = UserHandle.USER_NULL;
-    private Intent mSecondaryUserServiceIntent;
-    private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
-    private final UiEventLogger mUiEventLogger;
-    private final IActivityManager mActivityManager;
-    private final Executor mBgExecutor;
-    private final Executor mUiExecutor;
-    private final Executor mLongRunningExecutor;
-    private final boolean mGuestUserAutoCreated;
-    private final AtomicBoolean mGuestIsResetting;
-    private final AtomicBoolean mGuestCreationScheduled;
-    private FalsingManager mFalsingManager;
-    @Nullable
-    private View mView;
-    private String mCreateSupervisedUserPackage;
-    private GlobalSettings mGlobalSettings;
-    private List<UserSwitchCallback> mUserSwitchCallbacks =
-            Collections.synchronizedList(new ArrayList<>());
-
-    @Inject
-    public UserSwitcherControllerOldImpl(
-            Context context,
-            IActivityManager activityManager,
-            UserManager userManager,
-            UserTracker userTracker,
-            KeyguardStateController keyguardStateController,
-            DeviceProvisionedController deviceProvisionedController,
-            DevicePolicyManager devicePolicyManager,
-            @Main Handler handler,
-            ActivityStarter activityStarter,
-            BroadcastDispatcher broadcastDispatcher,
-            BroadcastSender broadcastSender,
-            UiEventLogger uiEventLogger,
-            FalsingManager falsingManager,
-            TelephonyListenerManager telephonyListenerManager,
-            SecureSettings secureSettings,
-            GlobalSettings globalSettings,
-            @Background Executor bgExecutor,
-            @LongRunning Executor longRunningExecutor,
-            @Main Executor uiExecutor,
-            InteractionJankMonitor interactionJankMonitor,
-            LatencyTracker latencyTracker,
-            DumpManager dumpManager,
-            DialogLaunchAnimator dialogLaunchAnimator,
-            GuestResumeSessionReceiver guestResumeSessionReceiver,
-            GuestResetOrExitSessionReceiver guestResetOrExitSessionReceiver) {
-        mContext = context;
-        mActivityManager = activityManager;
-        mUserTracker = userTracker;
-        mBroadcastDispatcher = broadcastDispatcher;
-        mBroadcastSender = broadcastSender;
-        mTelephonyListenerManager = telephonyListenerManager;
-        mUiEventLogger = uiEventLogger;
-        mFalsingManager = falsingManager;
-        mInteractionJankMonitor = interactionJankMonitor;
-        mLatencyTracker = latencyTracker;
-        mGlobalSettings = globalSettings;
-        mGuestResumeSessionReceiver = guestResumeSessionReceiver;
-        mGuestResetOrExitSessionReceiver = guestResetOrExitSessionReceiver;
-        mBgExecutor = bgExecutor;
-        mLongRunningExecutor = longRunningExecutor;
-        mUiExecutor = uiExecutor;
-        mGuestResumeSessionReceiver.register();
-        mGuestResetOrExitSessionReceiver.register();
-        mGuestUserAutoCreated = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_guestUserAutoCreated);
-        mGuestIsResetting = new AtomicBoolean();
-        mGuestCreationScheduled = new AtomicBoolean();
-        mKeyguardStateController = keyguardStateController;
-        mDeviceProvisionedController = deviceProvisionedController;
-        mDevicePolicyManager = devicePolicyManager;
-        mHandler = handler;
-        mActivityStarter = activityStarter;
-        mUserManager = userManager;
-        mDialogLaunchAnimator = dialogLaunchAnimator;
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_USER_ADDED);
-        filter.addAction(Intent.ACTION_USER_REMOVED);
-        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
-        filter.addAction(Intent.ACTION_USER_SWITCHED);
-        filter.addAction(Intent.ACTION_USER_STOPPED);
-        filter.addAction(Intent.ACTION_USER_UNLOCKED);
-        mBroadcastDispatcher.registerReceiver(
-                mReceiver, filter, null /* executor */,
-                UserHandle.SYSTEM, Context.RECEIVER_EXPORTED, null /* permission */);
-
-        mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
-
-        mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
-
-        filter = new IntentFilter();
-        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
-                PERMISSION_SELF, null /* scheduler */,
-                Context.RECEIVER_EXPORTED_UNAUDITED);
-
-        mSettingsObserver = new ContentObserver(mHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
-                mAddUsersFromLockScreen.setValue(
-                        mGlobalSettings.getIntForUser(
-                                Settings.Global.ADD_USERS_WHEN_LOCKED,
-                                0,
-                                UserHandle.USER_SYSTEM) != 0);
-                mUserSwitcherEnabled = mGlobalSettings.getIntForUser(
-                        Settings.Global.USER_SWITCHER_ENABLED, 0, UserHandle.USER_SYSTEM) != 0;
-                refreshUsers(UserHandle.USER_NULL);
-            };
-        };
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
-                mSettingsObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED), true,
-                mSettingsObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
-                mSettingsObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(
-                        Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
-                true, mSettingsObserver);
-        // Fetch initial values.
-        mSettingsObserver.onChange(false);
-
-        keyguardStateController.addCallback(mCallback);
-        listenForCallState();
-
-        mCreateSupervisedUserPackage = mContext.getString(
-                com.android.internal.R.string.config_supervisedUserCreationPackage);
-
-        dumpManager.registerDumpable(getClass().getSimpleName(), this);
-
-        refreshUsers(UserHandle.USER_NULL);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void refreshUsers(int forcePictureLoadForId) {
-        if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId + ")");
-        if (forcePictureLoadForId != UserHandle.USER_NULL) {
-            mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
-        }
-
-        if (mPauseRefreshUsers) {
-            return;
-        }
-
-        boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
-        SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
-        final int userCount = mUsers.size();
-        for (int i = 0; i < userCount; i++) {
-            UserRecord r = mUsers.get(i);
-            if (r == null || r.picture == null || r.info == null || forceAllUsers
-                    || mForcePictureLoadForUserId.get(r.info.id)) {
-                continue;
-            }
-            bitmaps.put(r.info.id, r.picture);
-        }
-        mForcePictureLoadForUserId.clear();
-
-        mBgExecutor.execute(() ->  {
-            List<UserInfo> infos = mUserManager.getAliveUsers();
-            if (infos == null) {
-                return;
-            }
-            ArrayList<UserRecord> records = new ArrayList<>(infos.size());
-            int currentId = mUserTracker.getUserId();
-            // Check user switchability of the foreground user since SystemUI is running in
-            // User 0
-            boolean canSwitchUsers = mUserManager.getUserSwitchability(
-                    UserHandle.of(mUserTracker.getUserId())) == SWITCHABILITY_STATUS_OK;
-            UserRecord guestRecord = null;
-
-            for (UserInfo info : infos) {
-                boolean isCurrent = currentId == info.id;
-                if (!mUserSwitcherEnabled && !info.isPrimary()) {
-                    continue;
-                }
-
-                if (info.isEnabled()) {
-                    if (info.isGuest()) {
-                        // Tapping guest icon triggers remove and a user switch therefore
-                        // the icon shouldn't be enabled even if the user is current
-                        guestRecord = LegacyUserDataHelper.createRecord(
-                                mContext,
-                                mUserManager,
-                                null /* picture */,
-                                info,
-                                isCurrent,
-                                canSwitchUsers);
-                    } else if (info.supportsSwitchToByUser()) {
-                        records.add(
-                                LegacyUserDataHelper.createRecord(
-                                        mContext,
-                                        mUserManager,
-                                        bitmaps.get(info.id),
-                                        info,
-                                        isCurrent,
-                                        canSwitchUsers));
-                    }
-                }
-            }
-
-            if (guestRecord == null) {
-                if (mGuestUserAutoCreated) {
-                    // If mGuestIsResetting=true, the switch should be disabled since
-                    // we will just use it as an indicator for "Resetting guest...".
-                    // Otherwise, default to canSwitchUsers.
-                    boolean isSwitchToGuestEnabled = !mGuestIsResetting.get() && canSwitchUsers;
-                    guestRecord = LegacyUserDataHelper.createRecord(
-                            mContext,
-                            currentId,
-                            UserActionModel.ENTER_GUEST_MODE,
-                            false /* isRestricted */,
-                            isSwitchToGuestEnabled);
-                    records.add(guestRecord);
-                } else if (canCreateGuest(guestRecord != null)) {
-                    guestRecord = LegacyUserDataHelper.createRecord(
-                            mContext,
-                            currentId,
-                            UserActionModel.ENTER_GUEST_MODE,
-                            false /* isRestricted */,
-                            canSwitchUsers);
-                    records.add(guestRecord);
-                }
-            } else {
-                records.add(guestRecord);
-            }
-
-            if (canCreateUser()) {
-                final UserRecord userRecord = LegacyUserDataHelper.createRecord(
-                        mContext,
-                        currentId,
-                        UserActionModel.ADD_USER,
-                        createIsRestricted(),
-                        canSwitchUsers);
-                records.add(userRecord);
-            }
-
-            if (canCreateSupervisedUser()) {
-                final UserRecord userRecord = LegacyUserDataHelper.createRecord(
-                        mContext,
-                        currentId,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        createIsRestricted(),
-                        canSwitchUsers);
-                records.add(userRecord);
-            }
-
-            if (canManageUsers()) {
-                records.add(LegacyUserDataHelper.createRecord(
-                        mContext,
-                        KeyguardUpdateMonitor.getCurrentUser(),
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                        /* isRestricted= */ false,
-                        /* isSwitchToEnabled= */ true
-                ));
-            }
-
-            mUiExecutor.execute(() -> {
-                if (records != null) {
-                    mUsers = records;
-                    notifyAdapters();
-                }
-            });
-        });
-    }
-
-    private boolean systemCanCreateUsers() {
-        return !mUserManager.hasBaseUserRestriction(
-                UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
-    }
-
-    private boolean currentUserCanCreateUsers() {
-        UserInfo currentUser = mUserTracker.getUserInfo();
-        return currentUser != null
-                && (currentUser.isAdmin() || mUserTracker.getUserId() == UserHandle.USER_SYSTEM)
-                && systemCanCreateUsers();
-    }
-
-    private boolean anyoneCanCreateUsers() {
-        return systemCanCreateUsers() && mAddUsersFromLockScreen.getValue();
-    }
-
-    @VisibleForTesting
-    boolean canCreateGuest(boolean hasExistingGuest) {
-        return mUserSwitcherEnabled
-                && (currentUserCanCreateUsers() || anyoneCanCreateUsers())
-                && !hasExistingGuest;
-    }
-
-    @VisibleForTesting
-    boolean canCreateUser() {
-        return mUserSwitcherEnabled
-                && (currentUserCanCreateUsers() || anyoneCanCreateUsers())
-                && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
-    }
-
-    @VisibleForTesting
-    boolean canManageUsers() {
-        UserInfo currentUser = mUserTracker.getUserInfo();
-        return mUserSwitcherEnabled
-                && ((currentUser != null && currentUser.isAdmin())
-                || mAddUsersFromLockScreen.getValue());
-    }
-
-    private boolean createIsRestricted() {
-        return !mAddUsersFromLockScreen.getValue();
-    }
-
-    @VisibleForTesting
-    boolean canCreateSupervisedUser() {
-        return !TextUtils.isEmpty(mCreateSupervisedUserPackage) && canCreateUser();
-    }
-
-    private void pauseRefreshUsers() {
-        if (!mPauseRefreshUsers) {
-            mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
-            mPauseRefreshUsers = true;
-        }
-    }
-
-    private void notifyAdapters() {
-        for (int i = mAdapters.size() - 1; i >= 0; i--) {
-            BaseUserSwitcherAdapter adapter = mAdapters.get(i).get();
-            if (adapter != null) {
-                adapter.notifyDataSetChanged();
-            } else {
-                mAdapters.remove(i);
-            }
-        }
-    }
-
-    @Override
-    public boolean isSimpleUserSwitcher() {
-        return mSimpleUserSwitcher;
-    }
-
-    /**
-     * Returns whether the current user is a system user.
-     */
-    @VisibleForTesting
-    boolean isSystemUser() {
-        return mUserTracker.getUserId() == UserHandle.USER_SYSTEM;
-    }
-
-    @Override
-    public @Nullable UserRecord getCurrentUserRecord() {
-        for (int i = 0; i < mUsers.size(); ++i) {
-            UserRecord userRecord = mUsers.get(i);
-            if (userRecord.isCurrent) {
-                return userRecord;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void onUserSelected(int userId, @Nullable DialogShower dialogShower) {
-        UserRecord userRecord = mUsers.stream()
-                .filter(x -> x.resolveId() == userId)
-                .findFirst()
-                .orElse(null);
-        if (userRecord == null) {
-            return;
-        }
-
-        onUserListItemClicked(userRecord, dialogShower);
-    }
-
-    @Override
-    public Flow<Boolean> isAddUsersFromLockScreenEnabled() {
-        return mAddUsersFromLockScreen;
-    }
-
-    @Override
-    public boolean isGuestUserAutoCreated() {
-        return mGuestUserAutoCreated;
-    }
-
-    @Override
-    public boolean isGuestUserResetting() {
-        return mGuestIsResetting.get();
-    }
-
-    @Override
-    public void onUserListItemClicked(UserRecord record, DialogShower dialogShower) {
-        if (record.isGuest && record.info == null) {
-            createAndSwitchToGuestUser(dialogShower);
-        } else if (record.isAddUser) {
-            showAddUserDialog(dialogShower);
-        } else if (record.isAddSupervisedUser) {
-            startSupervisedUserActivity();
-        } else if (record.isManageUsers) {
-            startActivity(new Intent(Settings.ACTION_USER_SETTINGS));
-        } else {
-            onUserListItemClicked(record.info.id, record, dialogShower);
-        }
-    }
-
-    private void onUserListItemClicked(int id, UserRecord record, DialogShower dialogShower) {
-        int currUserId = mUserTracker.getUserId();
-        // If switching from guest and guest is ephemeral, then follow the flow
-        // of showExitGuestDialog to remove current guest,
-        // and switch to selected user
-        UserInfo currUserInfo = mUserTracker.getUserInfo();
-        if (currUserId == id) {
-            if (record.isGuest) {
-                showExitGuestDialog(id, currUserInfo.isEphemeral(), dialogShower);
-            }
-            return;
-        }
-
-        if (currUserInfo != null && currUserInfo.isGuest()) {
-            showExitGuestDialog(currUserId, currUserInfo.isEphemeral(),
-                    record.resolveId(), dialogShower);
-            return;
-        }
-
-        if (dialogShower != null) {
-            // If we haven't morphed into another dialog, it means we have just switched users.
-            // Then, dismiss the dialog.
-            dialogShower.dismiss();
-        }
-        switchToUserId(id);
-    }
-
-    private void switchToUserId(int id) {
-        try {
-            if (mView != null) {
-                mInteractionJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
-                        .withView(InteractionJankMonitor.CUJ_USER_SWITCH, mView)
-                        .setTimeout(MULTI_USER_JOURNEY_TIMEOUT));
-            }
-            mLatencyTracker.onActionStart(LatencyTracker.ACTION_USER_SWITCH);
-            pauseRefreshUsers();
-            mActivityManager.switchUser(id);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't switch user.", e);
-        }
-    }
-
-    private void showExitGuestDialog(int id, boolean isGuestEphemeral, DialogShower dialogShower) {
-        int newId = UserHandle.USER_SYSTEM;
-        if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
-            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
-            if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
-                newId = info.id;
-            }
-        }
-        showExitGuestDialog(id, isGuestEphemeral, newId, dialogShower);
-    }
-
-    private void showExitGuestDialog(
-            int id,
-            boolean isGuestEphemeral,
-            int targetId,
-            DialogShower dialogShower) {
-        if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
-            mExitGuestDialog.cancel();
-        }
-        mExitGuestDialog = new ExitGuestDialog(
-                mContext,
-                id,
-                isGuestEphemeral,
-                targetId,
-                mKeyguardStateController.isShowing(),
-                mFalsingManager,
-                mDialogLaunchAnimator,
-                this::exitGuestUser);
-        if (dialogShower != null) {
-            dialogShower.showDialog(mExitGuestDialog, new DialogCuj(
-                    InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
-                    INTERACTION_JANK_EXIT_GUEST_MODE_TAG));
-        } else {
-            mExitGuestDialog.show();
-        }
-    }
-
-    @Override
-    public void createAndSwitchToGuestUser(@Nullable DialogShower dialogShower) {
-        createGuestAsync(guestId -> {
-            // guestId may be USER_NULL if we haven't reloaded the user list yet.
-            if (guestId != UserHandle.USER_NULL) {
-                mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD);
-                onUserListItemClicked(guestId, UserRecord.createForGuest(), dialogShower);
-            }
-        });
-    }
-
-    @Override
-    public void showAddUserDialog(@Nullable DialogShower dialogShower) {
-        if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
-            mAddUserDialog.cancel();
-        }
-        final UserInfo currentUser = mUserTracker.getUserInfo();
-        mAddUserDialog = new AddUserDialog(
-                mContext,
-                currentUser.getUserHandle(),
-                mKeyguardStateController.isShowing(),
-                /* showEphemeralMessage= */currentUser.isGuest() && currentUser.isEphemeral(),
-                mFalsingManager,
-                mBroadcastSender,
-                mDialogLaunchAnimator);
-        if (dialogShower != null) {
-            dialogShower.showDialog(mAddUserDialog,
-                    new DialogCuj(
-                            InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
-                            INTERACTION_JANK_ADD_NEW_USER_TAG
-                    ));
-        } else {
-            mAddUserDialog.show();
-        }
-    }
-
-    @Override
-    public void startSupervisedUserActivity() {
-        final Intent intent = new Intent()
-                .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
-                .setPackage(mCreateSupervisedUserPackage)
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        mContext.startActivity(intent);
-    }
-
-    private void listenForCallState() {
-        mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
-    }
-
-    private final TelephonyCallback.CallStateListener mPhoneStateListener =
-            new TelephonyCallback.CallStateListener() {
-        private int mCallState;
-
-        @Override
-        public void onCallStateChanged(int state) {
-            if (mCallState == state) return;
-            if (DEBUG) Log.v(TAG, "Call state changed: " + state);
-            mCallState = state;
-            refreshUsers(UserHandle.USER_NULL);
-        }
-    };
-
-    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (DEBUG) {
-                Log.v(TAG, "Broadcast: a=" + intent.getAction()
-                        + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
-            }
-
-            boolean unpauseRefreshUsers = false;
-            int forcePictureLoadForId = UserHandle.USER_NULL;
-
-            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-                if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
-                    mExitGuestDialog.cancel();
-                    mExitGuestDialog = null;
-                }
-
-                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                final UserInfo userInfo = mUserManager.getUserInfo(currentId);
-                final int userCount = mUsers.size();
-                for (int i = 0; i < userCount; i++) {
-                    UserRecord record = mUsers.get(i);
-                    if (record.info == null) continue;
-                    boolean shouldBeCurrent = record.info.id == currentId;
-                    if (record.isCurrent != shouldBeCurrent) {
-                        mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
-                    }
-                    if (shouldBeCurrent && !record.isGuest) {
-                        mLastNonGuestUser = record.info.id;
-                    }
-                    if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
-                        // Immediately remove restricted records in case the AsyncTask is too slow.
-                        mUsers.remove(i);
-                        i--;
-                    }
-                }
-                notifyUserSwitchCallbacks();
-                notifyAdapters();
-
-                // Disconnect from the old secondary user's service
-                if (mSecondaryUser != UserHandle.USER_NULL) {
-                    context.stopServiceAsUser(mSecondaryUserServiceIntent,
-                            UserHandle.of(mSecondaryUser));
-                    mSecondaryUser = UserHandle.USER_NULL;
-                }
-                // Connect to the new secondary user's service (purely to ensure that a persistent
-                // SystemUI application is created for that user)
-                if (userInfo != null && userInfo.id != UserHandle.USER_SYSTEM) {
-                    context.startServiceAsUser(mSecondaryUserServiceIntent,
-                            UserHandle.of(userInfo.id));
-                    mSecondaryUser = userInfo.id;
-                }
-                unpauseRefreshUsers = true;
-                if (mGuestUserAutoCreated) {
-                    // Guest user must be scheduled for creation AFTER switching to the target user.
-                    // This avoids lock contention which will produce UX bugs on the keyguard
-                    // (b/193933686).
-                    // TODO(b/191067027): Move guest user recreation to system_server
-                    guaranteeGuestPresent();
-                }
-            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
-                forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL);
-            } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
-                // Unlocking the system user may require a refresh
-                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-                if (userId != UserHandle.USER_SYSTEM) {
-                    return;
-                }
-            }
-            refreshUsers(forcePictureLoadForId);
-            if (unpauseRefreshUsers) {
-                mUnpauseRefreshUsers.run();
-            }
-        }
-    };
-
-    private final Runnable mUnpauseRefreshUsers = new Runnable() {
-        @Override
-        public void run() {
-            mHandler.removeCallbacks(this);
-            mPauseRefreshUsers = false;
-            refreshUsers(UserHandle.USER_NULL);
-        }
-    };
-
-    @Override
-    public void dump(PrintWriter pw, String[] args) {
-        pw.println("UserSwitcherController state:");
-        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
-        pw.print("  mUsers.size="); pw.println(mUsers.size());
-        for (int i = 0; i < mUsers.size(); i++) {
-            final UserRecord u = mUsers.get(i);
-            pw.print("    "); pw.println(u.toString());
-        }
-        pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher);
-        pw.println("mGuestUserAutoCreated=" + mGuestUserAutoCreated);
-    }
-
-    @Override
-    public String getCurrentUserName() {
-        if (mUsers.isEmpty()) return null;
-        UserRecord item = mUsers.stream().filter(x -> x.isCurrent).findFirst().orElse(null);
-        if (item == null || item.info == null) return null;
-        if (item.isGuest) return mContext.getString(com.android.internal.R.string.guest_name);
-        return item.info.name;
-    }
-
-    @Override
-    public void onDensityOrFontScaleChanged() {
-        refreshUsers(UserHandle.USER_ALL);
-    }
-
-    @Override
-    public void addAdapter(WeakReference<BaseUserSwitcherAdapter> adapter) {
-        mAdapters.add(adapter);
-    }
-
-    @Override
-    public ArrayList<UserRecord> getUsers() {
-        return mUsers;
-    }
-
-    @Override
-    public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) {
-        UserInfo currentUser = mUserTracker.getUserInfo();
-        if (currentUser.id != guestUserId) {
-            Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
-                    + " is not current user (" + currentUser.id + ")");
-            return;
-        }
-        if (!currentUser.isGuest()) {
-            Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
-                    + " is not a guest");
-            return;
-        }
-
-        boolean marked = mUserManager.markGuestForDeletion(currentUser.id);
-        if (!marked) {
-            Log.w(TAG, "Couldn't mark the guest for deletion for user " + guestUserId);
-            return;
-        }
-
-        if (targetUserId == UserHandle.USER_NULL) {
-            // Create a new guest in the foreground, and then immediately switch to it
-            createGuestAsync(newGuestId -> {
-                if (newGuestId == UserHandle.USER_NULL) {
-                    Log.e(TAG, "Could not create new guest, switching back to system user");
-                    switchToUserId(UserHandle.USER_SYSTEM);
-                    mUserManager.removeUser(currentUser.id);
-                    try {
-                        WindowManagerGlobal.getWindowManagerService().lockNow(/* options= */ null);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Couldn't remove guest because ActivityManager "
-                                + "or WindowManager is dead");
-                    }
-                    return;
-                }
-                switchToUserId(newGuestId);
-                mUserManager.removeUser(currentUser.id);
-            });
-        } else {
-            if (mGuestUserAutoCreated) {
-                mGuestIsResetting.set(true);
-            }
-            switchToUserId(targetUserId);
-            mUserManager.removeUser(currentUser.id);
-        }
-    }
-
-    @Override
-    public void exitGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId,
-            boolean forceRemoveGuestOnExit) {
-        UserInfo currentUser = mUserTracker.getUserInfo();
-        if (currentUser.id != guestUserId) {
-            Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
-                    + " is not current user (" + currentUser.id + ")");
-            return;
-        }
-        if (!currentUser.isGuest()) {
-            Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
-                    + " is not a guest");
-            return;
-        }
-
-        int newUserId = UserHandle.USER_SYSTEM;
-        if (targetUserId == UserHandle.USER_NULL) {
-            // when target user is not specified switch to last non guest user
-            if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
-                UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
-                if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
-                    newUserId = info.id;
-                }
-            }
-        } else {
-            newUserId = targetUserId;
-        }
-
-        if (currentUser.isEphemeral() || forceRemoveGuestOnExit) {
-            mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
-            removeGuestUser(currentUser.id, newUserId);
-        } else {
-            mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH);
-            switchToUserId(newUserId);
-        }
-    }
-
-    private void scheduleGuestCreation() {
-        if (!mGuestCreationScheduled.compareAndSet(false, true)) {
-            return;
-        }
-
-        mLongRunningExecutor.execute(() -> {
-            int newGuestId = createGuest();
-            mGuestCreationScheduled.set(false);
-            mGuestIsResetting.set(false);
-            if (newGuestId == UserHandle.USER_NULL) {
-                Log.w(TAG, "Could not create new guest while exiting existing guest");
-                // Refresh users so that we still display "Guest" if
-                // config_guestUserAutoCreated=true
-                refreshUsers(UserHandle.USER_NULL);
-            }
-        });
-
-    }
-
-    @Override
-    public void schedulePostBootGuestCreation() {
-        if (isDeviceAllowedToAddGuest()) {
-            guaranteeGuestPresent();
-        } else {
-            mDeviceProvisionedController.addCallback(mGuaranteeGuestPresentAfterProvisioned);
-        }
-    }
-
-    private boolean isDeviceAllowedToAddGuest() {
-        return mDeviceProvisionedController.isDeviceProvisioned()
-                && !mDevicePolicyManager.isDeviceManaged();
-    }
-
-    /**
-     * If there is no guest on the device, schedule creation of a new guest user in the background.
-     */
-    private void guaranteeGuestPresent() {
-        if (isDeviceAllowedToAddGuest() && mUserManager.findCurrentGuestUser() == null) {
-            scheduleGuestCreation();
-        }
-    }
-
-    private void createGuestAsync(Consumer<Integer> callback) {
-        final Dialog guestCreationProgressDialog =
-                new UserCreatingDialog(mContext, /* isGuest= */true);
-        guestCreationProgressDialog.show();
-
-        // userManager.createGuest will block the thread so post is needed for the dialog to show
-        mBgExecutor.execute(() -> {
-            final int guestId = createGuest();
-            mUiExecutor.execute(() -> {
-                guestCreationProgressDialog.dismiss();
-                if (guestId == UserHandle.USER_NULL) {
-                    Toast.makeText(mContext,
-                            com.android.settingslib.R.string.add_guest_failed,
-                            Toast.LENGTH_SHORT).show();
-                }
-                callback.accept(guestId);
-            });
-        });
-    }
-
-    /**
-     * Creates a guest user and return its multi-user user ID.
-     *
-     * This method does not check if a guest already exists before it makes a call to
-     * {@link UserManager} to create a new one.
-     *
-     * @return The multi-user user ID of the newly created guest user, or
-     * {@link UserHandle#USER_NULL} if the guest couldn't be created.
-     */
-    private @UserIdInt int createGuest() {
-        UserInfo guest;
-        try {
-            guest = mUserManager.createGuest(mContext);
-        } catch (UserManager.UserOperationException e) {
-            Log.e(TAG, "Couldn't create guest user", e);
-            return UserHandle.USER_NULL;
-        }
-        if (guest == null) {
-            Log.e(TAG, "Couldn't create guest, most likely because there already exists one");
-            return UserHandle.USER_NULL;
-        }
-        return guest.id;
-    }
-
-    @Override
-    public void init(View view) {
-        mView = view;
-    }
-
-    @Override
-    public boolean isKeyguardShowing() {
-        return mKeyguardStateController.isShowing();
-    }
-
-    private boolean shouldUseSimpleUserSwitcher() {
-        int defaultSimpleUserSwitcher = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0;
-        return mGlobalSettings.getIntForUser(SIMPLE_USER_SWITCHER_GLOBAL_SETTING,
-                defaultSimpleUserSwitcher, UserHandle.USER_SYSTEM) != 0;
-    }
-
-    @Override
-    public void startActivity(Intent intent) {
-        mActivityStarter.startActivity(intent, /* dismissShade= */ true);
-    }
-
-    @Override
-    public void addUserSwitchCallback(UserSwitchCallback callback) {
-        mUserSwitchCallbacks.add(callback);
-    }
-
-    @Override
-    public void removeUserSwitchCallback(UserSwitchCallback callback) {
-        mUserSwitchCallbacks.remove(callback);
-    }
-
-    /**
-     *  Notify user switch callbacks that user has switched.
-     */
-    private void notifyUserSwitchCallbacks() {
-        List<UserSwitchCallback> temp;
-        synchronized (mUserSwitchCallbacks) {
-            temp = new ArrayList<>(mUserSwitchCallbacks);
-        }
-        for (UserSwitchCallback callback : temp) {
-            callback.onUserSwitched();
-        }
-    }
-
-    private final KeyguardStateController.Callback mCallback =
-            new KeyguardStateController.Callback() {
-                @Override
-                public void onKeyguardShowingChanged() {
-
-                    // When Keyguard is going away, we don't need to update our items immediately
-                    // which
-                    // helps making the transition faster.
-                    if (!mKeyguardStateController.isShowing()) {
-                        mHandler.post(UserSwitcherControllerOldImpl.this::notifyAdapters);
-                    } else {
-                        notifyAdapters();
-                    }
-                }
-            };
-
-    private final DeviceProvisionedController.DeviceProvisionedListener
-            mGuaranteeGuestPresentAfterProvisioned =
-            new DeviceProvisionedController.DeviceProvisionedListener() {
-                @Override
-                public void onDeviceProvisionedChanged() {
-                    if (isDeviceAllowedToAddGuest()) {
-                        mBgExecutor.execute(
-                                () -> mDeviceProvisionedController.removeCallback(
-                                        mGuaranteeGuestPresentAfterProvisioned));
-                        guaranteeGuestPresent();
-                    }
-                }
-            };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 9866389..b135d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
@@ -28,6 +27,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings.Global;
@@ -46,7 +46,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.qs.SettingObserver;
-import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.Utils;
 import com.android.systemui.util.settings.GlobalSettings;
 
@@ -58,14 +58,15 @@
 
 /** Platform implementation of the zen mode controller. **/
 @SysUISingleton
-public class ZenModeControllerImpl extends CurrentUserTracker
-        implements ZenModeController, Dumpable {
+public class ZenModeControllerImpl implements ZenModeController, Dumpable {
     private static final String TAG = "ZenModeController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
     private final Object mCallbacksLock = new Object();
     private final Context mContext;
+    private final UserTracker mUserTracker;
+    private final BroadcastDispatcher mBroadcastDispatcher;
     private final SettingObserver mModeSetting;
     private final SettingObserver mConfigSetting;
     private final NotificationManager mNoMan;
@@ -80,23 +81,45 @@
     private long mZenUpdateTime;
     private NotificationManager.Policy mConsolidatedNotificationPolicy;
 
+    private final UserTracker.Callback mUserChangedCallback =
+            new UserTracker.Callback() {
+                @Override
+                public void onUserChanged(int newUser, Context userContext) {
+                    mUserId = newUser;
+                    if (mRegistered) {
+                        mBroadcastDispatcher.unregisterReceiver(mReceiver);
+                    }
+                    final IntentFilter filter = new IntentFilter(
+                            AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+                    filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
+                    mBroadcastDispatcher.registerReceiver(mReceiver, filter, null,
+                            UserHandle.of(mUserId));
+                    mRegistered = true;
+                    mSetupObserver.register();
+                }
+            };
+
     @Inject
     public ZenModeControllerImpl(
             Context context,
             @Main Handler handler,
             BroadcastDispatcher broadcastDispatcher,
             DumpManager dumpManager,
-            GlobalSettings globalSettings) {
-        super(broadcastDispatcher);
+            GlobalSettings globalSettings,
+            UserTracker userTracker) {
         mContext = context;
-        mModeSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE) {
+        mBroadcastDispatcher = broadcastDispatcher;
+        mUserTracker = userTracker;
+        mModeSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE,
+                userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
                 updateZenMode(value);
                 fireZenChanged(value);
             }
         };
-        mConfigSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE_CONFIG_ETAG) {
+        mConfigSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE_CONFIG_ETAG,
+                userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
                 updateZenModeConfig();
@@ -112,7 +135,7 @@
         mSetupObserver = new SetupObserver(handler);
         mSetupObserver.register();
         mUserManager = context.getSystemService(UserManager.class);
-        startTracking();
+        mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(handler));
 
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
@@ -120,7 +143,7 @@
     @Override
     public boolean isVolumeRestricted() {
         return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
-                new UserHandle(mUserId));
+                UserHandle.of(mUserId));
     }
 
     @Override
@@ -183,19 +206,6 @@
     }
 
     @Override
-    public void onUserSwitched(int userId) {
-        mUserId = userId;
-        if (mRegistered) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        final IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
-        filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
-        mContext.registerReceiverAsUser(mReceiver, new UserHandle(mUserId), filter, null, null);
-        mRegistered = true;
-        mSetupObserver.register();
-    }
-
-    @Override
     public ComponentName getEffectsSuppressor() {
         return NotificationManager.from(mContext).getEffectsSuppressor();
     }
@@ -208,7 +218,7 @@
 
     @Override
     public int getCurrentUser() {
-        return ActivityManager.getCurrentUser();
+        return mUserTracker.getUserId();
     }
 
     private void fireNextAlarmChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index b1b45b5..1b73539 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -58,8 +58,6 @@
 import com.android.systemui.statusbar.policy.SecurityControllerImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.UserSwitcherControllerImpl;
 import com.android.systemui.statusbar.policy.WalletController;
 import com.android.systemui.statusbar.policy.WalletControllerImpl;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -198,8 +196,4 @@
     static DataSaverController provideDataSaverController(NetworkController networkController) {
         return networkController.getDataSaverController();
     }
-
-    /** Binds {@link UserSwitcherController} to its implementation. */
-    @Binds
-    UserSwitcherController bindUserSwitcherController(UserSwitcherControllerImpl impl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/MultiRippleController.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/ripple/MultiRippleController.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
index 48df15c..93e78ac 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/MultiRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import androidx.annotation.VisibleForTesting
 
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/MultiRippleView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
similarity index 76%
rename from packages/SystemUI/src/com/android/systemui/ripple/MultiRippleView.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
index c7f0b7e..f558fee 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/MultiRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.content.Context
 import android.graphics.Canvas
@@ -31,11 +31,21 @@
 class MultiRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
 
     internal val ripples = ArrayList<RippleAnimation>()
+    private val listeners = ArrayList<RipplesFinishedListener>()
     private val ripplePaint = Paint()
     private var isWarningLogged = false
 
     companion object {
-        const val TAG = "MultiRippleView"
+        private const val TAG = "MultiRippleView"
+
+        interface RipplesFinishedListener {
+            /** Triggered when all the ripples finish running. */
+            fun onRipplesFinish()
+        }
+    }
+
+    fun addRipplesFinishedListener(listener: RipplesFinishedListener) {
+        listeners.add(listener)
     }
 
     override fun onDraw(canvas: Canvas?) {
@@ -62,6 +72,10 @@
             shouldInvalidate = shouldInvalidate || anim.isPlaying()
         }
 
-        if (shouldInvalidate) invalidate()
+        if (shouldInvalidate) {
+            invalidate()
+        } else { // Nothing is playing.
+            listeners.forEach { listener -> listener.onRipplesFinish() }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleAnimation.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/ripple/RippleAnimation.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index aca9e25..b2f8994 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleAnimationConfig.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/ripple/RippleAnimationConfig.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
index 8812254..773ac55 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleAnimationConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
@@ -1,4 +1,4 @@
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.graphics.Color
 
@@ -27,6 +27,6 @@
     companion object {
         const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
         const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
-        const val RIPPLE_DEFAULT_ALPHA: Int = 45 // full opacity is 255.
+        const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
similarity index 69%
rename from packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index d2f3a6a..a950d34 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.graphics.PointF
 import android.graphics.RuntimeShader
 import android.util.MathUtils
+import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
+import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
 
 /**
  * Shader class that renders an expanding ripple effect. The ripple contains three elements:
@@ -31,7 +33,7 @@
  * Modeled after frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java.
  */
 class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.CIRCLE) :
-        RuntimeShader(buildShader(rippleShape)) {
+    RuntimeShader(buildShader(rippleShape)) {
 
     /** Shapes that the [RippleShader] supports. */
     enum class RippleShape {
@@ -39,25 +41,30 @@
         ROUNDED_BOX,
         ELLIPSE
     }
-    //language=AGSL
+    // language=AGSL
     companion object {
-        private const val SHADER_UNIFORMS = """uniform vec2 in_center;
-                uniform vec2 in_size;
-                uniform float in_progress;
-                uniform float in_cornerRadius;
-                uniform float in_thickness;
-                uniform float in_time;
-                uniform float in_distort_radial;
-                uniform float in_distort_xy;
-                uniform float in_fadeSparkle;
-                uniform float in_fadeFill;
-                uniform float in_fadeRing;
-                uniform float in_blur;
-                uniform float in_pixelDensity;
-                layout(color) uniform vec4 in_color;
-                uniform float in_sparkle_strength;"""
+        private const val SHADER_UNIFORMS =
+            """
+            uniform vec2 in_center;
+            uniform vec2 in_size;
+            uniform float in_progress;
+            uniform float in_cornerRadius;
+            uniform float in_thickness;
+            uniform float in_time;
+            uniform float in_distort_radial;
+            uniform float in_distort_xy;
+            uniform float in_fadeSparkle;
+            uniform float in_fadeFill;
+            uniform float in_fadeRing;
+            uniform float in_blur;
+            uniform float in_pixelDensity;
+            layout(color) uniform vec4 in_color;
+            uniform float in_sparkle_strength;
+        """
 
-        private const val SHADER_CIRCLE_MAIN = """vec4 main(vec2 p) {
+        private const val SHADER_CIRCLE_MAIN =
+            """
+            vec4 main(vec2 p) {
                 vec2 p_distorted = distort(p, in_time, in_distort_radial, in_distort_xy);
                 float radius = in_size.x * 0.5;
                 float sparkleRing = soften(circleRing(p_distorted-in_center, radius), in_blur);
@@ -73,7 +80,9 @@
             }
         """
 
-        private const val SHADER_ROUNDED_BOX_MAIN = """vec4 main(vec2 p) {
+        private const val SHADER_ROUNDED_BOX_MAIN =
+            """
+            vec4 main(vec2 p) {
                 float sparkleRing = soften(roundedBoxRing(p-in_center, in_size, in_cornerRadius,
                     in_thickness), in_blur);
                 float inside = soften(sdRoundedBox(p-in_center, in_size * 1.2, in_cornerRadius),
@@ -89,7 +98,9 @@
             }
         """
 
-        private const val SHADER_ELLIPSE_MAIN = """vec4 main(vec2 p) {
+        private const val SHADER_ELLIPSE_MAIN =
+            """
+            vec4 main(vec2 p) {
                 vec2 p_distorted = distort(p, in_time, in_distort_radial, in_distort_xy);
 
                 float sparkleRing = soften(ellipseRing(p_distorted-in_center, in_size), in_blur);
@@ -105,22 +116,31 @@
             }
         """
 
-        private const val CIRCLE_SHADER = SHADER_UNIFORMS + RippleShaderUtilLibrary.SHADER_LIB +
-                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB + SdfShaderLibrary.CIRCLE_SDF +
+        private const val CIRCLE_SHADER =
+            SHADER_UNIFORMS +
+                ShaderUtilLibrary.SHADER_LIB +
+                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
+                SdfShaderLibrary.CIRCLE_SDF +
                 SHADER_CIRCLE_MAIN
-        private const val ROUNDED_BOX_SHADER = SHADER_UNIFORMS +
-                RippleShaderUtilLibrary.SHADER_LIB + SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
-                SdfShaderLibrary.ROUNDED_BOX_SDF + SHADER_ROUNDED_BOX_MAIN
-        private const val ELLIPSE_SHADER = SHADER_UNIFORMS + RippleShaderUtilLibrary.SHADER_LIB +
-                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB + SdfShaderLibrary.ELLIPSE_SDF +
+        private const val ROUNDED_BOX_SHADER =
+            SHADER_UNIFORMS +
+                ShaderUtilLibrary.SHADER_LIB +
+                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
+                SdfShaderLibrary.ROUNDED_BOX_SDF +
+                SHADER_ROUNDED_BOX_MAIN
+        private const val ELLIPSE_SHADER =
+            SHADER_UNIFORMS +
+                ShaderUtilLibrary.SHADER_LIB +
+                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
+                SdfShaderLibrary.ELLIPSE_SDF +
                 SHADER_ELLIPSE_MAIN
 
         private fun buildShader(rippleShape: RippleShape): String =
-                when (rippleShape) {
-                    RippleShape.CIRCLE -> CIRCLE_SHADER
-                    RippleShape.ROUNDED_BOX -> ROUNDED_BOX_SHADER
-                    RippleShape.ELLIPSE -> ELLIPSE_SHADER
-                }
+            when (rippleShape) {
+                RippleShape.CIRCLE -> CIRCLE_SHADER
+                RippleShape.ROUNDED_BOX -> ROUNDED_BOX_SHADER
+                RippleShape.ELLIPSE -> ELLIPSE_SHADER
+            }
 
         private fun subProgress(start: Float, end: Float, progress: Float): Float {
             val min = Math.min(start, end)
@@ -130,9 +150,7 @@
         }
     }
 
-    /**
-     * Sets the center position of the ripple.
-     */
+    /** Sets the center position of the ripple. */
     fun setCenter(x: Float, y: Float) {
         setFloatUniform("in_center", x, y)
     }
@@ -144,21 +162,21 @@
         maxSize.y = height
     }
 
-    /**
-     * Progress of the ripple. Float value between [0, 1].
-     */
+    /** Progress of the ripple. Float value between [0, 1]. */
     var progress: Float = 0.0f
         set(value) {
             field = value
             setFloatUniform("in_progress", value)
             val curvedProg = 1 - (1 - value) * (1 - value) * (1 - value)
 
-            setFloatUniform("in_size", /* width= */ maxSize.x * curvedProg,
-                    /* height= */ maxSize.y * curvedProg)
+            setFloatUniform(
+                "in_size",
+                /* width= */ maxSize.x * curvedProg,
+                /* height= */ maxSize.y * curvedProg
+            )
             setFloatUniform("in_thickness", maxSize.y * curvedProg * 0.5f)
             // radius should not exceed width and height values.
-            setFloatUniform("in_cornerRadius",
-                    Math.min(maxSize.x, maxSize.y) * curvedProg)
+            setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * curvedProg)
 
             setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value))
 
@@ -175,18 +193,14 @@
             setFloatUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
         }
 
-    /**
-     * Play time since the start of the effect.
-     */
+    /** Play time since the start of the effect. */
     var time: Float = 0.0f
         set(value) {
             field = value
             setFloatUniform("in_time", value)
         }
 
-    /**
-     * A hex value representing the ripple color, in the format of ARGB
-     */
+    /** A hex value representing the ripple color, in the format of ARGB */
     var color: Int = 0xffffff
         set(value) {
             field = value
@@ -194,9 +208,9 @@
         }
 
     /**
-     * Noise sparkle intensity. Expected value between [0, 1]. The sparkle is white, and thus
-     * with strength 0 it's transparent, leaving the ripple fully smooth, while with strength 1
-     * it's opaque white and looks the most grainy.
+     * Noise sparkle intensity. Expected value between [0, 1]. The sparkle is white, and thus with
+     * strength 0 it's transparent, leaving the ripple fully smooth, while with strength 1 it's
+     * opaque white and looks the most grainy.
      */
     var sparkleStrength: Float = 0.0f
         set(value) {
@@ -204,9 +218,7 @@
             setFloatUniform("in_sparkle_strength", value)
         }
 
-    /**
-     * Distortion strength of the ripple. Expected value between[0, 1].
-     */
+    /** Distortion strength of the ripple. Expected value between[0, 1]. */
     var distortionStrength: Float = 0.0f
         set(value) {
             field = value
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
similarity index 77%
rename from packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index a6d7930..2ad8243 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
@@ -26,7 +26,7 @@
 import android.util.AttributeSet
 import android.view.View
 import androidx.core.graphics.ColorUtils
-import com.android.systemui.ripple.RippleShader.RippleShape
+import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape
 
 /**
  * A generic expanding ripple effect.
@@ -98,17 +98,20 @@
             rippleShader.time = now.toFloat()
             invalidate()
         }
-        animator.addListener(object : AnimatorListenerAdapter() {
-            override fun onAnimationEnd(animation: Animator?) {
-                onAnimationEnd?.run()
+        animator.addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator?) {
+                    onAnimationEnd?.run()
+                }
             }
-        })
+        )
         animator.start()
     }
 
-    /** Set the color to be used for the ripple.
+    /**
+     * Set the color to be used for the ripple.
      *
-     * The alpha value of the color will be applied to the ripple. The alpha range is [0-100].
+     * The alpha value of the color will be applied to the ripple. The alpha range is [0-255].
      */
     fun setColor(color: Int, alpha: Int = RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA) {
         rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
@@ -123,9 +126,7 @@
         rippleShader.rippleFill = rippleFill
     }
 
-    /**
-     * Set the intensity of the sparkles.
-     */
+    /** Set the intensity of the sparkles. */
     fun setSparkleStrength(strength: Float) {
         rippleShader.sparkleStrength = strength
     }
@@ -143,20 +144,30 @@
         // active effect area. Values here should be kept in sync with the animation implementation
         // in the ripple shader.
         if (rippleShape == RippleShape.CIRCLE) {
-            val maskRadius = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
-                    (1 - rippleShader.progress)) * maxWidth
+            val maskRadius =
+                (1 -
+                    (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress)) * maxWidth
             canvas.drawCircle(centerX, centerY, maskRadius, ripplePaint)
         } else {
-            val maskWidth = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
-                    (1 - rippleShader.progress)) * maxWidth * 2
-            val maskHeight = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
-                    (1 - rippleShader.progress)) * maxHeight * 2
+            val maskWidth =
+                (1 -
+                    (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress)) * maxWidth * 2
+            val maskHeight =
+                (1 -
+                    (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress) *
+                        (1 - rippleShader.progress)) * maxHeight * 2
             canvas.drawRect(
-                    /* left= */ centerX - maskWidth,
-                    /* top= */ centerY - maskHeight,
-                    /* right= */ centerX + maskWidth,
-                    /* bottom= */ centerY + maskHeight,
-                    ripplePaint)
+                /* left= */ centerX - maskWidth,
+                /* top= */ centerY - maskHeight,
+                /* right= */ centerX + maskWidth,
+                /* bottom= */ centerY + maskHeight,
+                ripplePaint
+            )
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
rename to packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
index 5e256c6..8b2f466 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.shaderutil
 
 /** Library class that contains 2D signed distance functions. */
 class SdfShaderLibrary {
-    //language=AGSL
+    // language=AGSL
     companion object {
-        const val CIRCLE_SDF = """
+        const val CIRCLE_SDF =
+            """
             float sdCircle(vec2 p, float r) {
                 return (length(p)-r) / r;
             }
@@ -34,7 +35,8 @@
             }
         """
 
-        const val ROUNDED_BOX_SDF = """
+        const val ROUNDED_BOX_SDF =
+            """
             float sdRoundedBox(vec2 p, vec2 size, float cornerRadius) {
                 size *= 0.5;
                 cornerRadius *= 0.5;
@@ -58,7 +60,8 @@
         // Used non-trigonometry parametrization and Halley's method (iterative) for root finding.
         // This is more expensive than the regular circle SDF, recommend to use the circle SDF if
         // possible.
-        const val ELLIPSE_SDF = """float sdEllipse(vec2 p, vec2 wh) {
+        const val ELLIPSE_SDF =
+            """float sdEllipse(vec2 p, vec2 wh) {
             wh *= 0.5;
 
             // symmetry
@@ -98,7 +101,8 @@
         }
         """
 
-        const val SHADER_SDF_OPERATION_LIB = """
+        const val SHADER_SDF_OPERATION_LIB =
+            """
             float soften(float d, float blur) {
                 float blurHalf = blur * 0.5;
                 return smoothstep(-blurHalf, blurHalf, d);
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
new file mode 100644
index 0000000..d78e0c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.shaderutil
+
+/** A common utility functions that are used for computing shaders. */
+class ShaderUtilLibrary {
+    // language=AGSL
+    companion object {
+        const val SHADER_LIB =
+            """
+            float triangleNoise(vec2 n) {
+                n  = fract(n * vec2(5.3987, 5.4421));
+                n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
+                float xy = n.x * n.y;
+                // compute in [0..2[ and remap to [-1.0..1.0[
+                return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
+            }
+
+            const float PI = 3.1415926535897932384626;
+
+            float sparkles(vec2 uv, float t) {
+                float n = triangleNoise(uv);
+                float s = 0.0;
+                for (float i = 0; i < 4; i += 1) {
+                    float l = i * 0.01;
+                    float h = l + 0.1;
+                    float o = smoothstep(n - l, h, n);
+                    o *= abs(sin(PI * o * (t + 0.55 * i)));
+                    s += o;
+                }
+                return s;
+            }
+
+            vec2 distort(vec2 p, float time, float distort_amount_radial,
+                float distort_amount_xy) {
+                    float angle = atan(p.y, p.x);
+                      return p + vec2(sin(angle * 8 + time * 0.003 + 1.641),
+                                cos(angle * 5 + 2.14 + time * 0.00412)) * distort_amount_radial
+                         + vec2(sin(p.x * 0.01 + time * 0.00215 + 0.8123),
+                                cos(p.y * 0.01 + time * 0.005931)) * distort_amount_xy;
+            }
+
+            // Return range [-1, 1].
+            vec3 hash(vec3 p) {
+                p = fract(p * vec3(.3456, .1234, .9876));
+                p += dot(p, p.yxz + 43.21);
+                p = (p.xxy + p.yxx) * p.zyx;
+                return (fract(sin(p) * 4567.1234567) - .5) * 2.;
+            }
+
+            // Skew factors (non-uniform).
+            const float SKEW = 0.3333333;  // 1/3
+            const float UNSKEW = 0.1666667;  // 1/6
+
+            // Return range roughly [-1,1].
+            // It's because the hash function (that returns a random gradient vector) returns
+            // different magnitude of vectors. Noise doesn't have to be in the precise range thus
+            // skipped normalize.
+            float simplex3d(vec3 p) {
+                // Skew the input coordinate, so that we get squashed cubical grid
+                vec3 s = floor(p + (p.x + p.y + p.z) * SKEW);
+
+                // Unskew back
+                vec3 u = s - (s.x + s.y + s.z) * UNSKEW;
+
+                // Unskewed coordinate that is relative to p, to compute the noise contribution
+                // based on the distance.
+                vec3 c0 = p - u;
+
+                // We have six simplices (in this case tetrahedron, since we are in 3D) that we
+                // could possibly in.
+                // Here, we are finding the correct tetrahedron (simplex shape), and traverse its
+                // four vertices (c0..3) when computing noise contribution.
+                // The way we find them is by comparing c0's x,y,z values.
+                // For example in 2D, we can find the triangle (simplex shape in 2D) that we are in
+                // by comparing x and y values. i.e. x>y lower, x<y, upper triangle.
+                // Same applies in 3D.
+                //
+                // Below indicates the offsets (or offset directions) when c0=(x0,y0,z0)
+                // x0>y0>z0: (1,0,0), (1,1,0), (1,1,1)
+                // x0>z0>y0: (1,0,0), (1,0,1), (1,1,1)
+                // z0>x0>y0: (0,0,1), (1,0,1), (1,1,1)
+                // z0>y0>x0: (0,0,1), (0,1,1), (1,1,1)
+                // y0>z0>x0: (0,1,0), (0,1,1), (1,1,1)
+                // y0>x0>z0: (0,1,0), (1,1,0), (1,1,1)
+                //
+                // The rule is:
+                // * For offset1, set 1 at the max component, otherwise 0.
+                // * For offset2, set 0 at the min component, otherwise 1.
+                // * For offset3, set 1 for all.
+                //
+                // Encode x0-y0, y0-z0, z0-x0 in a vec3
+                vec3 en = c0 - c0.yzx;
+                // Each represents whether x0>y0, y0>z0, z0>x0
+                en = step(vec3(0.), en);
+                // en.zxy encodes z0>x0, x0>y0, y0>x0
+                vec3 offset1 = en * (1. - en.zxy); // find max
+                vec3 offset2 = 1. - en.zxy * (1. - en); // 1-(find min)
+                vec3 offset3 = vec3(1.);
+
+                vec3 c1 = c0 - offset1 + UNSKEW;
+                vec3 c2 = c0 - offset2 + UNSKEW * 2.;
+                vec3 c3 = c0 - offset3 + UNSKEW * 3.;
+
+                // Kernel summation: dot(max(0, r^2-d^2))^4, noise contribution)
+                //
+                // First compute d^2, squared distance to the point.
+                vec4 w; // w = max(0, r^2 - d^2))
+                w.x = dot(c0, c0);
+                w.y = dot(c1, c1);
+                w.z = dot(c2, c2);
+                w.w = dot(c3, c3);
+
+                // Noise contribution should decay to zero before they cross the simplex boundary.
+                // Usually r^2 is 0.5 or 0.6;
+                // 0.5 ensures continuity but 0.6 increases the visual quality for the application
+                // where discontinuity isn't noticeable.
+                w = max(0.6 - w, 0.);
+
+                // Noise contribution from each point.
+                vec4 nc;
+                nc.x = dot(hash(s), c0);
+                nc.y = dot(hash(s + offset1), c1);
+                nc.z = dot(hash(s + offset2), c2);
+                nc.w = dot(hash(s + offset3), c3);
+
+                nc *= w*w*w*w;
+
+                // Add all the noise contributions.
+                // Should multiply by the possible max contribution to adjust the range in [-1,1].
+                return dot(vec4(32.), nc);
+            }
+            """
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
new file mode 100644
index 0000000..5ac3aad7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+import android.graphics.BlendMode
+import android.graphics.Color
+
+/** Turbulence noise animation configuration. */
+data class TurbulenceNoiseAnimationConfig(
+    /** The number of grids that is used to generate noise. */
+    val gridCount: Float = DEFAULT_NOISE_GRID_COUNT,
+
+    /** Multiplier for the noise luma matte. Increase this for brighter effects. */
+    val luminosityMultiplier: Float = DEFAULT_LUMINOSITY_MULTIPLIER,
+
+    /**
+     * Noise move speed variables.
+     *
+     * Its sign determines the direction; magnitude determines the speed. <ul>
+     * ```
+     *     <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
+     *     <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
+     *     <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
+     *     to add turbulence in place.
+     * ```
+     * </ul>
+     */
+    val noiseMoveSpeedX: Float = 0f,
+    val noiseMoveSpeedY: Float = 0f,
+    val noiseMoveSpeedZ: Float = DEFAULT_NOISE_SPEED_Z,
+
+    /** Color of the effect. */
+    var color: Int = DEFAULT_COLOR,
+    /** Background color of the effect. */
+    val backgroundColor: Int = DEFAULT_BACKGROUND_COLOR,
+    val opacity: Int = DEFAULT_OPACITY,
+    val width: Float = 0f,
+    val height: Float = 0f,
+    val duration: Float = DEFAULT_NOISE_DURATION_IN_MILLIS,
+    val pixelDensity: Float = 1f,
+    val blendMode: BlendMode = DEFAULT_BLEND_MODE,
+    val onAnimationEnd: Runnable? = null
+) {
+    companion object {
+        const val DEFAULT_NOISE_DURATION_IN_MILLIS = 7500F
+        const val DEFAULT_LUMINOSITY_MULTIPLIER = 1f
+        const val DEFAULT_NOISE_GRID_COUNT = 1.2f
+        const val DEFAULT_NOISE_SPEED_Z = 0.3f
+        const val DEFAULT_OPACITY = 150 // full opacity is 255.
+        const val DEFAULT_COLOR = Color.WHITE
+        const val DEFAULT_BACKGROUND_COLOR = Color.BLACK
+        val DEFAULT_BLEND_MODE = BlendMode.SRC_OVER
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
new file mode 100644
index 0000000..4c7e5f4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+/** A controller that plays [TurbulenceNoiseView]. */
+class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoiseView) {
+    /** Updates the color of the noise. */
+    fun updateNoiseColor(color: Int) {
+        turbulenceNoiseView.updateColor(color)
+    }
+
+    // TODO: add cancel and/ or pause once design requirements become clear.
+    /** Plays [TurbulenceNoiseView] with the given config. */
+    fun play(turbulenceNoiseAnimationConfig: TurbulenceNoiseAnimationConfig) {
+        turbulenceNoiseView.play(turbulenceNoiseAnimationConfig)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
new file mode 100644
index 0000000..19c114d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+import android.graphics.RuntimeShader
+import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
+import java.lang.Float.max
+
+/** Shader that renders turbulence simplex noise, with no octave. */
+class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) {
+    // language=AGSL
+    companion object {
+        private const val UNIFORMS =
+            """
+            uniform float in_gridNum;
+            uniform vec3 in_noiseMove;
+            uniform vec2 in_size;
+            uniform float in_aspectRatio;
+            uniform float in_opacity;
+            uniform float in_pixelDensity;
+            layout(color) uniform vec4 in_color;
+            layout(color) uniform vec4 in_backgroundColor;
+        """
+
+        private const val SHADER_LIB =
+            """
+            float getLuminosity(vec3 c) {
+                return 0.3*c.r + 0.59*c.g + 0.11*c.b;
+            }
+
+            vec3 maskLuminosity(vec3 dest, float lum) {
+                dest.rgb *= vec3(lum);
+                // Clip back into the legal range
+                dest = clamp(dest, vec3(0.), vec3(1.0));
+                return dest;
+            }
+        """
+
+        private const val MAIN_SHADER =
+            """
+            vec4 main(vec2 p) {
+                vec2 uv = p / in_size.xy;
+                uv.x *= in_aspectRatio;
+
+                vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
+                float luma = simplex3d(noiseP) * in_opacity;
+                vec3 mask = maskLuminosity(in_color.rgb, luma);
+                vec3 color = in_backgroundColor.rgb + mask * 0.6;
+
+                // Add dither with triangle distribution to avoid color banding. Ok to dither in the
+                // shader here as we are in gamma space.
+                float dither = triangleNoise(p * in_pixelDensity) / 255.;
+
+                // The result color should be pre-multiplied, i.e. [R*A, G*A, B*A, A], thus need to
+                // multiply rgb with a to get the correct result.
+                color = (color + dither.rrr) * in_color.a;
+                return vec4(color, in_color.a);
+            }
+        """
+
+        private const val TURBULENCE_NOISE_SHADER =
+            ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SHADER_LIB + MAIN_SHADER
+    }
+
+    /** Sets the number of grid for generating noise. */
+    fun setGridCount(gridNumber: Float = 1.0f) {
+        setFloatUniform("in_gridNum", gridNumber)
+    }
+
+    /**
+     * Sets the pixel density of the screen.
+     *
+     * Used it for noise dithering.
+     */
+    fun setPixelDensity(pixelDensity: Float) {
+        setFloatUniform("in_pixelDensity", pixelDensity)
+    }
+
+    /** Sets the noise color of the effect. */
+    fun setColor(color: Int) {
+        setColorUniform("in_color", color)
+    }
+
+    /** Sets the background color of the effect. */
+    fun setBackgroundColor(color: Int) {
+        setColorUniform("in_backgroundColor", color)
+    }
+
+    /**
+     * Sets the opacity to achieve fade in/ out of the animation.
+     *
+     * Expected value range is [1, 0].
+     */
+    fun setOpacity(opacity: Float) {
+        setFloatUniform("in_opacity", opacity)
+    }
+
+    /** Sets the size of the shader. */
+    fun setSize(width: Float, height: Float) {
+        setFloatUniform("in_size", width, height)
+        setFloatUniform("in_aspectRatio", width / max(height, 0.001f))
+    }
+
+    /** Sets noise move speed in x, y, and z direction. */
+    fun setNoiseMove(x: Float, y: Float, z: Float) {
+        setFloatUniform("in_noiseMove", x, y, z)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
new file mode 100644
index 0000000..8649d59
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import androidx.core.graphics.ColorUtils
+import java.util.Random
+import kotlin.math.sin
+
+/** View that renders turbulence noise effect. */
+class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+
+    companion object {
+        private const val MS_TO_SEC = 0.001f
+        private const val TWO_PI = Math.PI.toFloat() * 2f
+    }
+
+    @VisibleForTesting val turbulenceNoiseShader = TurbulenceNoiseShader()
+    private val paint = Paint().apply { this.shader = turbulenceNoiseShader }
+    private val random = Random()
+    private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
+    private var config: TurbulenceNoiseAnimationConfig? = null
+
+    val isPlaying: Boolean
+        get() = animator.isRunning
+
+    init {
+        // Only visible during the animation.
+        visibility = INVISIBLE
+    }
+
+    /** Updates the color during the animation. No-op if there's no animation playing. */
+    fun updateColor(color: Int) {
+        config?.let {
+            it.color = color
+            applyConfig(it)
+        }
+    }
+
+    override fun onDraw(canvas: Canvas?) {
+        if (canvas == null || !canvas.isHardwareAccelerated) {
+            // Drawing with the turbulence noise shader requires hardware acceleration, so skip
+            // if it's unsupported.
+            return
+        }
+
+        canvas.drawPaint(paint)
+    }
+
+    internal fun play(config: TurbulenceNoiseAnimationConfig) {
+        if (isPlaying) {
+            return // Ignore if the animation is playing.
+        }
+        visibility = VISIBLE
+        applyConfig(config)
+
+        // Add random offset to avoid same patterned noise.
+        val offsetX = random.nextFloat()
+        val offsetY = random.nextFloat()
+
+        animator.duration = config.duration.toLong()
+        animator.addUpdateListener { updateListener ->
+            val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
+            // Remap [0,1] to [0, 2*PI]
+            val progress = TWO_PI * updateListener.animatedValue as Float
+
+            turbulenceNoiseShader.setNoiseMove(
+                offsetX + timeInSec * config.noiseMoveSpeedX,
+                offsetY + timeInSec * config.noiseMoveSpeedY,
+                timeInSec * config.noiseMoveSpeedZ
+            )
+
+            // Fade in and out the noise as the animation progress.
+            // TODO: replace it with a better curve
+            turbulenceNoiseShader.setOpacity(sin(TWO_PI - progress) * config.luminosityMultiplier)
+
+            invalidate()
+        }
+
+        animator.addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator) {
+                    visibility = INVISIBLE
+                    config.onAnimationEnd?.run()
+                }
+            }
+        )
+        animator.start()
+    }
+
+    private fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
+        this.config = config
+        with(turbulenceNoiseShader) {
+            setGridCount(config.gridCount)
+            setColor(ColorUtils.setAlphaComponent(config.color, config.opacity))
+            setBackgroundColor(config.backgroundColor)
+            setSize(config.width, config.height)
+            setPixelDensity(config.pixelDensity)
+        }
+        paint.blendMode = config.blendMode
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
index 4cb41f3..a9d05d1 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
@@ -65,8 +65,7 @@
         height = WindowManager.LayoutParams.WRAP_CONTENT
         type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
         flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
-            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
-            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
         format = PixelFormat.TRANSLUCENT
         setTrustedOverlay()
     }
@@ -95,6 +94,13 @@
     private var wakeReasonAcquired: String? = null
 
     /**
+     * A stack of pairs of device id and temporary view info. This is used when there may be
+     * multiple devices in range, and we want to always display the chip for the most recently
+     * active device.
+     */
+    internal val activeViews: ArrayDeque<Pair<String, T>> = ArrayDeque()
+
+    /**
      * Displays the view with the provided [newInfo].
      *
      * This method handles inflating and attaching the view, then delegates to [updateView] to
@@ -103,6 +109,12 @@
     fun displayView(newInfo: T) {
         val currentDisplayInfo = displayInfo
 
+        // Update our list of active devices by removing it if necessary, then adding back at the
+        // front of the list
+        val id = newInfo.id
+        val position = findAndRemoveFromActiveViewsList(id)
+        activeViews.addFirst(Pair(id, newInfo))
+
         if (currentDisplayInfo != null &&
             currentDisplayInfo.info.windowTitle == newInfo.windowTitle) {
             // We're already displaying information in the correctly-titled window, so we just need
@@ -114,27 +126,37 @@
                 // We're already displaying information but that information is under a different
                 // window title. So, we need to remove the old window with the old title and add a
                 // new window with the new title.
-                removeView(removalReason = "New info has new window title: ${newInfo.windowTitle}")
+                removeView(
+                    id,
+                    removalReason = "New info has new window title: ${newInfo.windowTitle}"
+                )
             }
 
             // At this point, we're guaranteed to no longer be displaying a view.
             // So, set up all our callbacks and inflate the view.
             configurationController.addCallback(displayScaleListener)
-            // Wake the screen if necessary so the user will see the view. (Per b/239426653, we want
-            // the view to show over the dream state, so we should only wake up if the screen is
-            // completely off.)
-            if (!powerManager.isScreenOn) {
-                wakeLock = wakeLockBuilder
+
+            wakeLock = if (!powerManager.isScreenOn) {
+                // If the screen is off, fully wake it so the user can see the view.
+                wakeLockBuilder
                     .setTag(newInfo.windowTitle)
                     .setLevelsAndFlags(
-                        PowerManager.FULL_WAKE_LOCK or
-                        PowerManager.ACQUIRE_CAUSES_WAKEUP
+                            PowerManager.FULL_WAKE_LOCK or
+                                PowerManager.ACQUIRE_CAUSES_WAKEUP
                     )
                     .build()
-                wakeLock?.acquire(newInfo.wakeReason)
-                wakeReasonAcquired = newInfo.wakeReason
+            } else {
+                // Per b/239426653, we want the view to show over the dream state.
+                // If the screen is on, using screen bright level will leave screen on the dream
+                // state but ensure the screen will not go off before wake lock is released.
+                wakeLockBuilder
+                    .setTag(newInfo.windowTitle)
+                    .setLevelsAndFlags(PowerManager.SCREEN_BRIGHT_WAKE_LOCK)
+                    .build()
             }
-            logger.logViewAddition(newInfo.windowTitle)
+            wakeLock?.acquire(newInfo.wakeReason)
+            wakeReasonAcquired = newInfo.wakeReason
+            logger.logViewAddition(id, newInfo.windowTitle)
             inflateAndUpdateView(newInfo)
         }
 
@@ -145,9 +167,13 @@
             // include it just to be safe.
             FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS
        )
-        cancelViewTimeout?.run()
+
+        // Only cancel timeout of the most recent view displayed, as it will be reset.
+        if (position == 0) {
+            cancelViewTimeout?.run()
+        }
         cancelViewTimeout = mainExecutor.executeDelayed(
-            { removeView(REMOVAL_REASON_TIMEOUT) },
+            { removeView(id, REMOVAL_REASON_TIMEOUT) },
             timeout.toLong()
         )
     }
@@ -190,28 +216,67 @@
     }
 
     /**
-     * Hides the view.
+     * Hides the view given its [id].
      *
+     * @param id the id of the device responsible of displaying the temp view.
      * @param removalReason a short string describing why the view was removed (timeout, state
      *     change, etc.)
      */
-    fun removeView(removalReason: String) {
+    fun removeView(id: String, removalReason: String) {
         val currentDisplayInfo = displayInfo ?: return
 
+        val removalPosition = findAndRemoveFromActiveViewsList(id)
+        if (removalPosition == null) {
+            logger.logViewRemovalIgnored(id, "view not found in the list")
+            return
+        }
+        if (removalPosition != 0) {
+            logger.logViewRemovalIgnored(id, "most recent view is being displayed.")
+            return
+        }
+        logger.logViewRemoval(id, removalReason)
+
+        val newViewToDisplay = if (activeViews.isEmpty()) {
+            null
+        } else {
+            activeViews[0].second
+        }
+
         val currentView = currentDisplayInfo.view
         animateViewOut(currentView) {
             windowManager.removeView(currentView)
             wakeLock?.release(wakeReasonAcquired)
         }
 
-        logger.logViewRemoval(removalReason)
         configurationController.removeCallback(displayScaleListener)
         // Re-set to null immediately (instead as part of the animation end runnable) so
-        // that if a new view event comes in while this view is animating out, we still display the
-        // new view appropriately.
+        // that if a new view event comes in while this view is animating out, we still display
+        // the new view appropriately.
         displayInfo = null
         // No need to time the view out since it's already gone
         cancelViewTimeout?.run()
+
+        if (newViewToDisplay != null) {
+            mainExecutor.executeDelayed({ displayView(newViewToDisplay)}, DISPLAY_VIEW_DELAY)
+        }
+    }
+
+    /**
+     * Finds and removes the active view with the given [id] from the stack, or null if there is no
+     * active view with that ID
+     *
+     * @param id that temporary view belonged to.
+     *
+     * @return index of the view in the stack , otherwise null.
+     */
+    private fun findAndRemoveFromActiveViewsList(id: String): Int? {
+        for (i in 0 until activeViews.size) {
+            if (activeViews[i].first == id) {
+                activeViews.removeAt(i)
+                return i
+            }
+        }
+        return null
     }
 
     /**
@@ -252,6 +317,7 @@
 }
 
 private const val REMOVAL_REASON_TIMEOUT = "TIMEOUT"
+const val DISPLAY_VIEW_DELAY = 50L
 
 private data class IconInfo(
     val iconName: String,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
index cbb5002..df83960 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
@@ -37,6 +37,11 @@
      * disappears.
      */
     open val timeoutMs: Int = DEFAULT_TIMEOUT_MILLIS
+
+    /**
+     * The id of the temporary view.
+     */
+    abstract val id: String
 }
 
 const val DEFAULT_TIMEOUT_MILLIS = 10000
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
index 428a104..133a384 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
@@ -24,13 +24,42 @@
     internal val buffer: LogBuffer,
     internal val tag: String,
 ) {
-    /** Logs that we added the view in a window titled [windowTitle]. */
-    fun logViewAddition(windowTitle: String) {
-        buffer.log(tag, LogLevel.DEBUG, { str1 = windowTitle }, { "View added. window=$str1" })
+    /** Logs that we added the view with the given [id] in a window titled [windowTitle]. */
+    fun logViewAddition(id: String, windowTitle: String) {
+        buffer.log(
+            tag,
+            LogLevel.DEBUG,
+            {
+                str1 = windowTitle
+                str2 = id
+            },
+            { "View added. window=$str1 id=$str2" }
+        )
     }
 
-    /** Logs that we removed the chip for the given [reason]. */
-    fun logViewRemoval(reason: String) {
-        buffer.log(tag, LogLevel.DEBUG, { str1 = reason }, { "View removed due to: $str1" })
+    /** Logs that we removed the view with the given [id] for the given [reason]. */
+    fun logViewRemoval(id: String, reason: String) {
+        buffer.log(
+            tag,
+            LogLevel.DEBUG,
+            {
+                str1 = reason
+                str2 = id
+            },
+            { "View with id=$str2 is removed due to: $str1" }
+        )
+    }
+
+    /** Logs that we ignored removal of the view with the given [id]. */
+    fun logViewRemovalIgnored(id: String, reason: String) {
+        buffer.log(
+            tag,
+            LogLevel.DEBUG,
+            {
+                str1 = reason
+                str2 = id
+            },
+            { "Removal of view with id=$str2 is ignored because $str1" }
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index 6237365..b92e0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -40,6 +40,7 @@
     override val windowTitle: String,
     override val wakeReason: String,
     override val timeoutMs: Int,
+    override val id: String,
 ) : TemporaryViewInfo()
 
 /** The possible items to display at the end of the chipbar. */
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index bf70673..e8a22ec 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -46,6 +46,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.SystemUIApplication;
+import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.util.NotificationChannels;
 
@@ -61,15 +62,24 @@
     private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME";
     private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD";
     private final Context mContext;
+    private final BroadcastDispatcher mBroadcastDispatcher;
 
     // TODO: delay some notifications to avoid bumpy fast operations
 
-    private NotificationManager mNotificationManager;
-    private StorageManager mStorageManager;
+    private final NotificationManager mNotificationManager;
+    private final StorageManager mStorageManager;
 
     @Inject
-    public StorageNotification(Context context) {
+    public StorageNotification(
+            Context context,
+            BroadcastDispatcher broadcastDispatcher,
+            NotificationManager notificationManager,
+            StorageManager storageManager
+    ) {
         mContext = context;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mNotificationManager = notificationManager;
+        mStorageManager = storageManager;
     }
 
     private static class MoveInfo {
@@ -168,17 +178,22 @@
 
     @Override
     public void start() {
-        mNotificationManager = mContext.getSystemService(NotificationManager.class);
-
-        mStorageManager = mContext.getSystemService(StorageManager.class);
         mStorageManager.registerListener(mListener);
 
-        mContext.registerReceiver(mSnoozeReceiver, new IntentFilter(ACTION_SNOOZE_VOLUME),
-                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null,
-                Context.RECEIVER_EXPORTED_UNAUDITED);
-        mContext.registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_WIZARD),
-                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null,
-                Context.RECEIVER_EXPORTED_UNAUDITED);
+        mBroadcastDispatcher.registerReceiver(
+                mSnoozeReceiver,
+                new IntentFilter(ACTION_SNOOZE_VOLUME),
+                null,
+                null,
+                Context.RECEIVER_EXPORTED_UNAUDITED,
+                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+        mBroadcastDispatcher.registerReceiver(
+                mFinishReceiver,
+                new IntentFilter(ACTION_FINISH_WIZARD),
+                null,
+                null,
+                Context.RECEIVER_EXPORTED_UNAUDITED,
+                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
         // Kick current state into place
         final List<DiskInfo> disks = mStorageManager.getDisks();
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index ffaf524..ed53de7 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -19,31 +19,18 @@
 
 import android.content.Context
 import android.content.pm.UserInfo
-import android.graphics.drawable.BitmapDrawable
-import android.graphics.drawable.Drawable
 import android.os.UserHandle
 import android.os.UserManager
 import android.provider.Settings
 import androidx.annotation.VisibleForTesting
-import androidx.appcompat.content.res.AppCompatResources
-import com.android.internal.util.UserIcons
-import com.android.systemui.R
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.common.shared.model.Text
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.user.data.model.UserSwitcherSettingsModel
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.user.shared.model.UserModel
 import com.android.systemui.util.settings.GlobalSettings
 import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
 import java.util.concurrent.atomic.AtomicBoolean
@@ -55,7 +42,6 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
@@ -72,15 +58,6 @@
  * upstream changes.
  */
 interface UserRepository {
-    /** List of all users on the device. */
-    val users: Flow<List<UserModel>>
-
-    /** The currently-selected user. */
-    val selectedUser: Flow<UserModel>
-
-    /** List of available user-related actions. */
-    val actions: Flow<List<UserActionModel>>
-
     /** User switcher related settings. */
     val userSwitcherSettings: Flow<UserSwitcherSettingsModel>
 
@@ -93,9 +70,6 @@
     /** User ID of the last non-guest selected user. */
     val lastSelectedNonGuestUserId: Int
 
-    /** Whether actions are available even when locked. */
-    val isActionableWhenLocked: Flow<Boolean>
-
     /** Whether the device is configured to always have a guest user available. */
     val isGuestUserAutoCreated: Boolean
 
@@ -125,18 +99,13 @@
 constructor(
     @Application private val appContext: Context,
     private val manager: UserManager,
-    private val controller: UserSwitcherController,
     @Application private val applicationScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val globalSettings: GlobalSettings,
     private val tracker: UserTracker,
-    private val featureFlags: FeatureFlags,
 ) : UserRepository {
 
-    private val isNewImpl: Boolean
-        get() = !featureFlags.isEnabled(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER)
-
     private val _userSwitcherSettings = MutableStateFlow(runBlocking { getSettings() })
     override val userSwitcherSettings: Flow<UserSwitcherSettingsModel> =
         _userSwitcherSettings.asStateFlow().filterNotNull()
@@ -150,58 +119,11 @@
     override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
         private set
 
-    private val userRecords: Flow<List<UserRecord>> = conflatedCallbackFlow {
-        fun send() {
-            trySendWithFailureLogging(
-                controller.users,
-                TAG,
-            )
-        }
-
-        val callback = UserSwitcherController.UserSwitchCallback { send() }
-
-        controller.addUserSwitchCallback(callback)
-        send()
-
-        awaitClose { controller.removeUserSwitchCallback(callback) }
-    }
-
-    override val users: Flow<List<UserModel>> =
-        userRecords.map { records -> records.filter { it.isUser() }.map { it.toUserModel() } }
-
-    override val selectedUser: Flow<UserModel> =
-        users.map { users -> users.first { user -> user.isSelected } }
-
-    override val actions: Flow<List<UserActionModel>> =
-        userRecords.map { records -> records.filter { it.isNotUser() }.map { it.toActionModel() } }
-
-    override val isActionableWhenLocked: Flow<Boolean> =
-        if (isNewImpl) {
-            emptyFlow()
-        } else {
-            controller.isAddUsersFromLockScreenEnabled
-        }
-
     override val isGuestUserAutoCreated: Boolean =
-        if (isNewImpl) {
-            appContext.resources.getBoolean(com.android.internal.R.bool.config_guestUserAutoCreated)
-        } else {
-            controller.isGuestUserAutoCreated
-        }
+        appContext.resources.getBoolean(com.android.internal.R.bool.config_guestUserAutoCreated)
 
     private var _isGuestUserResetting: Boolean = false
-    override var isGuestUserResetting: Boolean =
-        if (isNewImpl) {
-            _isGuestUserResetting
-        } else {
-            controller.isGuestUserResetting
-        }
-        set(value) =
-            if (isNewImpl) {
-                _isGuestUserResetting = value
-            } else {
-                error("Not supported in the old implementation!")
-            }
+    override var isGuestUserResetting: Boolean = _isGuestUserResetting
 
     override val isGuestUserCreationScheduled = AtomicBoolean()
 
@@ -210,10 +132,8 @@
     override var isRefreshUsersPaused: Boolean = false
 
     init {
-        if (isNewImpl) {
-            observeSelectedUser()
-            observeUserSettings()
-        }
+        observeSelectedUser()
+        observeUserSettings()
     }
 
     override fun refreshUsers() {
@@ -327,64 +247,6 @@
         }
     }
 
-    private fun UserRecord.isUser(): Boolean {
-        return when {
-            isAddUser -> false
-            isAddSupervisedUser -> false
-            isManageUsers -> false
-            isGuest -> info != null
-            else -> true
-        }
-    }
-
-    private fun UserRecord.isNotUser(): Boolean {
-        return !isUser()
-    }
-
-    private fun UserRecord.toUserModel(): UserModel {
-        return UserModel(
-            id = resolveId(),
-            name = getUserName(this),
-            image = getUserImage(this),
-            isSelected = isCurrent,
-            isSelectable = isSwitchToEnabled || isGuest,
-            isGuest = isGuest,
-        )
-    }
-
-    private fun UserRecord.toActionModel(): UserActionModel {
-        return when {
-            isAddUser -> UserActionModel.ADD_USER
-            isAddSupervisedUser -> UserActionModel.ADD_SUPERVISED_USER
-            isGuest -> UserActionModel.ENTER_GUEST_MODE
-            isManageUsers -> UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
-            else -> error("Don't know how to convert to UserActionModel: $this")
-        }
-    }
-
-    private fun getUserName(record: UserRecord): Text {
-        val resourceId: Int? = LegacyUserUiHelper.getGuestUserRecordNameResourceId(record)
-        return if (resourceId != null) {
-            Text.Resource(resourceId)
-        } else {
-            Text.Loaded(checkNotNull(record.info).name)
-        }
-    }
-
-    private fun getUserImage(record: UserRecord): Drawable {
-        if (record.isGuest) {
-            return checkNotNull(
-                AppCompatResources.getDrawable(appContext, R.drawable.ic_account_circle)
-            )
-        }
-
-        val userId = checkNotNull(record.info?.id)
-        return manager.getUserIcon(userId)?.let { userSelectedIcon ->
-            BitmapDrawable(userSelectedIcon)
-        }
-            ?: UserIcons.getDefaultUserIcon(appContext.resources, userId, /* light= */ false)
-    }
-
     companion object {
         private const val TAG = "UserRepository"
         @VisibleForTesting const val SETTING_SIMPLE_USER_SWITCHER = "lockscreenSimpleUserSwitcher"
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index dda78aa..516c650 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -39,13 +39,11 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
+import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.user.data.source.UserRecord
 import com.android.systemui.user.domain.model.ShowDialogRequestModel
@@ -64,8 +62,7 @@
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
@@ -82,10 +79,8 @@
 constructor(
     @Application private val applicationContext: Context,
     private val repository: UserRepository,
-    private val controller: UserSwitcherController,
     private val activityStarter: ActivityStarter,
     private val keyguardInteractor: KeyguardInteractor,
-    private val featureFlags: FeatureFlags,
     private val manager: UserManager,
     @Application private val applicationScope: CoroutineScope,
     telephonyInteractor: TelephonyInteractor,
@@ -107,9 +102,6 @@
         fun onUserStateChanged()
     }
 
-    private val isNewImpl: Boolean
-        get() = !featureFlags.isEnabled(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER)
-
     private val supervisedUserPackageName: String?
         get() =
             applicationContext.getString(
@@ -118,185 +110,145 @@
 
     private val callbackMutex = Mutex()
     private val callbacks = mutableSetOf<UserCallback>()
+    private val userInfos =
+        combine(repository.userSwitcherSettings, repository.userInfos) { settings, userInfos ->
+            userInfos.filter { !it.isGuest || canCreateGuestUser(settings) }
+        }
 
     /** List of current on-device users to select from. */
     val users: Flow<List<UserModel>>
         get() =
-            if (isNewImpl) {
-                combine(
-                    repository.userInfos,
-                    repository.selectedUserInfo,
-                    repository.userSwitcherSettings,
-                ) { userInfos, selectedUserInfo, settings ->
-                    toUserModels(
-                        userInfos = userInfos,
-                        selectedUserId = selectedUserInfo.id,
-                        isUserSwitcherEnabled = settings.isUserSwitcherEnabled,
-                    )
-                }
-            } else {
-                repository.users
+            combine(
+                userInfos,
+                repository.selectedUserInfo,
+                repository.userSwitcherSettings,
+            ) { userInfos, selectedUserInfo, settings ->
+                toUserModels(
+                    userInfos = userInfos,
+                    selectedUserId = selectedUserInfo.id,
+                    isUserSwitcherEnabled = settings.isUserSwitcherEnabled,
+                )
             }
 
     /** The currently-selected user. */
     val selectedUser: Flow<UserModel>
         get() =
-            if (isNewImpl) {
-                combine(
-                    repository.selectedUserInfo,
-                    repository.userSwitcherSettings,
-                ) { selectedUserInfo, settings ->
-                    val selectedUserId = selectedUserInfo.id
-                    checkNotNull(
-                        toUserModel(
-                            userInfo = selectedUserInfo,
-                            selectedUserId = selectedUserId,
-                            canSwitchUsers = canSwitchUsers(selectedUserId),
-                            isUserSwitcherEnabled = settings.isUserSwitcherEnabled,
-                        )
+            combine(
+                repository.selectedUserInfo,
+                repository.userSwitcherSettings,
+            ) { selectedUserInfo, settings ->
+                val selectedUserId = selectedUserInfo.id
+                checkNotNull(
+                    toUserModel(
+                        userInfo = selectedUserInfo,
+                        selectedUserId = selectedUserId,
+                        canSwitchUsers = canSwitchUsers(selectedUserId),
+                        isUserSwitcherEnabled = settings.isUserSwitcherEnabled,
                     )
-                }
-            } else {
-                repository.selectedUser
+                )
             }
 
     /** List of user-switcher related actions that are available. */
     val actions: Flow<List<UserActionModel>>
         get() =
-            if (isNewImpl) {
-                combine(
-                    repository.selectedUserInfo,
-                    repository.userInfos,
-                    repository.userSwitcherSettings,
-                    keyguardInteractor.isKeyguardShowing,
-                ) { _, userInfos, settings, isDeviceLocked ->
-                    buildList {
-                        val hasGuestUser = userInfos.any { it.isGuest }
-                        if (
-                            !hasGuestUser &&
-                                (guestUserInteractor.isGuestUserAutoCreated ||
-                                    UserActionsUtil.canCreateGuest(
-                                        manager,
-                                        repository,
-                                        settings.isUserSwitcherEnabled,
-                                        settings.isAddUsersFromLockscreen,
-                                    ))
-                        ) {
-                            add(UserActionModel.ENTER_GUEST_MODE)
-                        }
+            combine(
+                repository.selectedUserInfo,
+                userInfos,
+                repository.userSwitcherSettings,
+                keyguardInteractor.isKeyguardShowing,
+            ) { _, userInfos, settings, isDeviceLocked ->
+                buildList {
+                    val hasGuestUser = userInfos.any { it.isGuest }
+                    if (!hasGuestUser && canCreateGuestUser(settings)) {
+                        add(UserActionModel.ENTER_GUEST_MODE)
+                    }
 
-                        if (!isDeviceLocked || settings.isAddUsersFromLockscreen) {
-                            // The device is locked and our setting to allow actions that add users
-                            // from the lock-screen is not enabled. The guest action from above is
-                            // always allowed, even when the device is locked, but the various "add
-                            // user" actions below are not. We can finish building the list here.
+                    if (!isDeviceLocked || settings.isAddUsersFromLockscreen) {
+                        // The device is locked and our setting to allow actions that add users
+                        // from the lock-screen is not enabled. The guest action from above is
+                        // always allowed, even when the device is locked, but the various "add
+                        // user" actions below are not. We can finish building the list here.
 
-                            val canCreateUsers =
-                                UserActionsUtil.canCreateUser(
-                                    manager,
-                                    repository,
-                                    settings.isUserSwitcherEnabled,
-                                    settings.isAddUsersFromLockscreen,
-                                )
-
-                            if (canCreateUsers) {
-                                add(UserActionModel.ADD_USER)
-                            }
-
-                            if (
-                                UserActionsUtil.canCreateSupervisedUser(
-                                    manager,
-                                    repository,
-                                    settings.isUserSwitcherEnabled,
-                                    settings.isAddUsersFromLockscreen,
-                                    supervisedUserPackageName,
-                                )
-                            ) {
-                                add(UserActionModel.ADD_SUPERVISED_USER)
-                            }
-                        }
-
-                        if (
-                            UserActionsUtil.canManageUsers(
+                        val canCreateUsers =
+                            UserActionsUtil.canCreateUser(
+                                manager,
                                 repository,
                                 settings.isUserSwitcherEnabled,
                                 settings.isAddUsersFromLockscreen,
                             )
-                        ) {
-                            add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
+
+                        if (canCreateUsers) {
+                            add(UserActionModel.ADD_USER)
                         }
+
+                        if (
+                            UserActionsUtil.canCreateSupervisedUser(
+                                manager,
+                                repository,
+                                settings.isUserSwitcherEnabled,
+                                settings.isAddUsersFromLockscreen,
+                                supervisedUserPackageName,
+                            )
+                        ) {
+                            add(UserActionModel.ADD_SUPERVISED_USER)
+                        }
+                    }
+
+                    if (
+                        UserActionsUtil.canManageUsers(
+                            repository,
+                            settings.isUserSwitcherEnabled,
+                            settings.isAddUsersFromLockscreen,
+                        )
+                    ) {
+                        add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
                     }
                 }
-            } else {
-                combine(
-                        repository.isActionableWhenLocked,
-                        keyguardInteractor.isKeyguardShowing,
-                    ) { isActionableWhenLocked, isLocked ->
-                        isActionableWhenLocked || !isLocked
-                    }
-                    .flatMapLatest { isActionable ->
-                        if (isActionable) {
-                            repository.actions
-                        } else {
-                            // If not actionable it means that we're not allowed to show actions
-                            // when
-                            // locked and we are locked. Therefore, we should show no actions.
-                            flowOf(emptyList())
-                        }
-                    }
             }
 
     val userRecords: StateFlow<ArrayList<UserRecord>> =
-        if (isNewImpl) {
-            combine(
-                    repository.userInfos,
-                    repository.selectedUserInfo,
-                    actions,
-                    repository.userSwitcherSettings,
-                ) { userInfos, selectedUserInfo, actionModels, settings ->
-                    ArrayList(
-                        userInfos.map {
+        combine(
+                userInfos,
+                repository.selectedUserInfo,
+                actions,
+                repository.userSwitcherSettings,
+            ) { userInfos, selectedUserInfo, actionModels, settings ->
+                ArrayList(
+                    userInfos.map {
+                        toRecord(
+                            userInfo = it,
+                            selectedUserId = selectedUserInfo.id,
+                        )
+                    } +
+                        actionModels.map {
                             toRecord(
-                                userInfo = it,
+                                action = it,
                                 selectedUserId = selectedUserInfo.id,
+                                isRestricted =
+                                    it != UserActionModel.ENTER_GUEST_MODE &&
+                                        it != UserActionModel.NAVIGATE_TO_USER_MANAGEMENT &&
+                                        !settings.isAddUsersFromLockscreen,
                             )
-                        } +
-                            actionModels.map {
-                                toRecord(
-                                    action = it,
-                                    selectedUserId = selectedUserInfo.id,
-                                    isRestricted =
-                                        it != UserActionModel.ENTER_GUEST_MODE &&
-                                            it != UserActionModel.NAVIGATE_TO_USER_MANAGEMENT &&
-                                            !settings.isAddUsersFromLockscreen,
-                                )
-                            }
-                    )
-                }
-                .onEach { notifyCallbacks() }
-                .stateIn(
-                    scope = applicationScope,
-                    started = SharingStarted.Eagerly,
-                    initialValue = ArrayList(),
+                        }
                 )
-        } else {
-            MutableStateFlow(ArrayList())
-        }
+            }
+            .onEach { notifyCallbacks() }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.Eagerly,
+                initialValue = ArrayList(),
+            )
 
     val selectedUserRecord: StateFlow<UserRecord?> =
-        if (isNewImpl) {
-            repository.selectedUserInfo
-                .map { selectedUserInfo ->
-                    toRecord(userInfo = selectedUserInfo, selectedUserId = selectedUserInfo.id)
-                }
-                .stateIn(
-                    scope = applicationScope,
-                    started = SharingStarted.Eagerly,
-                    initialValue = null,
-                )
-        } else {
-            MutableStateFlow(null)
-        }
+        repository.selectedUserInfo
+            .map { selectedUserInfo ->
+                toRecord(userInfo = selectedUserInfo, selectedUserId = selectedUserInfo.id)
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.Eagerly,
+                initialValue = null,
+            )
 
     /** Whether the device is configured to always have a guest user available. */
     val isGuestUserAutoCreated: Boolean = guestUserInteractor.isGuestUserAutoCreated
@@ -311,44 +263,37 @@
     val dialogDismissRequests: Flow<Unit?> = _dialogDismissRequests.asStateFlow()
 
     val isSimpleUserSwitcher: Boolean
-        get() =
-            if (isNewImpl) {
-                repository.isSimpleUserSwitcher()
-            } else {
-                error("Not supported in the old implementation!")
-            }
+        get() = repository.isSimpleUserSwitcher()
 
     init {
-        if (isNewImpl) {
-            refreshUsersScheduler.refreshIfNotPaused()
-            telephonyInteractor.callState
-                .distinctUntilChanged()
-                .onEach { refreshUsersScheduler.refreshIfNotPaused() }
-                .launchIn(applicationScope)
+        refreshUsersScheduler.refreshIfNotPaused()
+        telephonyInteractor.callState
+            .distinctUntilChanged()
+            .onEach { refreshUsersScheduler.refreshIfNotPaused() }
+            .launchIn(applicationScope)
 
-            combine(
-                    broadcastDispatcher.broadcastFlow(
-                        filter =
-                            IntentFilter().apply {
-                                addAction(Intent.ACTION_USER_ADDED)
-                                addAction(Intent.ACTION_USER_REMOVED)
-                                addAction(Intent.ACTION_USER_INFO_CHANGED)
-                                addAction(Intent.ACTION_USER_SWITCHED)
-                                addAction(Intent.ACTION_USER_STOPPED)
-                                addAction(Intent.ACTION_USER_UNLOCKED)
-                            },
-                        user = UserHandle.SYSTEM,
-                        map = { intent, _ -> intent },
-                    ),
-                    repository.selectedUserInfo.pairwise(null),
-                ) { intent, selectedUserChange ->
-                    Pair(intent, selectedUserChange.previousValue)
-                }
-                .onEach { (intent, previousSelectedUser) ->
-                    onBroadcastReceived(intent, previousSelectedUser)
-                }
-                .launchIn(applicationScope)
-        }
+        combine(
+                broadcastDispatcher.broadcastFlow(
+                    filter =
+                        IntentFilter().apply {
+                            addAction(Intent.ACTION_USER_ADDED)
+                            addAction(Intent.ACTION_USER_REMOVED)
+                            addAction(Intent.ACTION_USER_INFO_CHANGED)
+                            addAction(Intent.ACTION_USER_SWITCHED)
+                            addAction(Intent.ACTION_USER_STOPPED)
+                            addAction(Intent.ACTION_USER_UNLOCKED)
+                        },
+                    user = UserHandle.SYSTEM,
+                    map = { intent, _ -> intent },
+                ),
+                repository.selectedUserInfo.pairwise(null),
+            ) { intent, selectedUserChange ->
+                Pair(intent, selectedUserChange.previousValue)
+            }
+            .onEach { (intent, previousSelectedUser) ->
+                onBroadcastReceived(intent, previousSelectedUser)
+            }
+            .launchIn(applicationScope)
     }
 
     fun addCallback(callback: UserCallback) {
@@ -414,48 +359,43 @@
         newlySelectedUserId: Int,
         dialogShower: UserSwitchDialogController.DialogShower? = null,
     ) {
-        if (isNewImpl) {
-            val currentlySelectedUserInfo = repository.getSelectedUserInfo()
-            if (
-                newlySelectedUserId == currentlySelectedUserInfo.id &&
-                    currentlySelectedUserInfo.isGuest
-            ) {
-                // Here when clicking on the currently-selected guest user to leave guest mode
-                // and return to the previously-selected non-guest user.
-                showDialog(
-                    ShowDialogRequestModel.ShowExitGuestDialog(
-                        guestUserId = currentlySelectedUserInfo.id,
-                        targetUserId = repository.lastSelectedNonGuestUserId,
-                        isGuestEphemeral = currentlySelectedUserInfo.isEphemeral,
-                        isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
-                        onExitGuestUser = this::exitGuestUser,
-                        dialogShower = dialogShower,
-                    )
+        val currentlySelectedUserInfo = repository.getSelectedUserInfo()
+        if (
+            newlySelectedUserId == currentlySelectedUserInfo.id && currentlySelectedUserInfo.isGuest
+        ) {
+            // Here when clicking on the currently-selected guest user to leave guest mode
+            // and return to the previously-selected non-guest user.
+            showDialog(
+                ShowDialogRequestModel.ShowExitGuestDialog(
+                    guestUserId = currentlySelectedUserInfo.id,
+                    targetUserId = repository.lastSelectedNonGuestUserId,
+                    isGuestEphemeral = currentlySelectedUserInfo.isEphemeral,
+                    isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
+                    onExitGuestUser = this::exitGuestUser,
+                    dialogShower = dialogShower,
                 )
-                return
-            }
-
-            if (currentlySelectedUserInfo.isGuest) {
-                // Here when switching from guest to a non-guest user.
-                showDialog(
-                    ShowDialogRequestModel.ShowExitGuestDialog(
-                        guestUserId = currentlySelectedUserInfo.id,
-                        targetUserId = newlySelectedUserId,
-                        isGuestEphemeral = currentlySelectedUserInfo.isEphemeral,
-                        isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
-                        onExitGuestUser = this::exitGuestUser,
-                        dialogShower = dialogShower,
-                    )
-                )
-                return
-            }
-
-            dialogShower?.dismiss()
-
-            switchUser(newlySelectedUserId)
-        } else {
-            controller.onUserSelected(newlySelectedUserId, dialogShower)
+            )
+            return
         }
+
+        if (currentlySelectedUserInfo.isGuest) {
+            // Here when switching from guest to a non-guest user.
+            showDialog(
+                ShowDialogRequestModel.ShowExitGuestDialog(
+                    guestUserId = currentlySelectedUserInfo.id,
+                    targetUserId = newlySelectedUserId,
+                    isGuestEphemeral = currentlySelectedUserInfo.isEphemeral,
+                    isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
+                    onExitGuestUser = this::exitGuestUser,
+                    dialogShower = dialogShower,
+                )
+            )
+            return
+        }
+
+        dialogShower?.dismiss()
+
+        switchUser(newlySelectedUserId)
     }
 
     /** Executes the given action. */
@@ -463,51 +403,38 @@
         action: UserActionModel,
         dialogShower: UserSwitchDialogController.DialogShower? = null,
     ) {
-        if (isNewImpl) {
-            when (action) {
-                UserActionModel.ENTER_GUEST_MODE ->
-                    guestUserInteractor.createAndSwitchTo(
-                        this::showDialog,
-                        this::dismissDialog,
-                    ) { userId ->
-                        selectUser(userId, dialogShower)
-                    }
-                UserActionModel.ADD_USER -> {
-                    val currentUser = repository.getSelectedUserInfo()
-                    showDialog(
-                        ShowDialogRequestModel.ShowAddUserDialog(
-                            userHandle = currentUser.userHandle,
-                            isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
-                            showEphemeralMessage = currentUser.isGuest && currentUser.isEphemeral,
-                            dialogShower = dialogShower,
-                        )
-                    )
+        when (action) {
+            UserActionModel.ENTER_GUEST_MODE ->
+                guestUserInteractor.createAndSwitchTo(
+                    this::showDialog,
+                    this::dismissDialog,
+                ) { userId ->
+                    selectUser(userId, dialogShower)
                 }
-                UserActionModel.ADD_SUPERVISED_USER ->
-                    activityStarter.startActivity(
-                        Intent()
-                            .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
-                            .setPackage(supervisedUserPackageName)
-                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
-                        /* dismissShade= */ true,
+            UserActionModel.ADD_USER -> {
+                val currentUser = repository.getSelectedUserInfo()
+                showDialog(
+                    ShowDialogRequestModel.ShowAddUserDialog(
+                        userHandle = currentUser.userHandle,
+                        isKeyguardShowing = keyguardInteractor.isKeyguardShowing(),
+                        showEphemeralMessage = currentUser.isGuest && currentUser.isEphemeral,
+                        dialogShower = dialogShower,
                     )
-                UserActionModel.NAVIGATE_TO_USER_MANAGEMENT ->
-                    activityStarter.startActivity(
-                        Intent(Settings.ACTION_USER_SETTINGS),
-                        /* dismissShade= */ true,
-                    )
+                )
             }
-        } else {
-            when (action) {
-                UserActionModel.ENTER_GUEST_MODE -> controller.createAndSwitchToGuestUser(null)
-                UserActionModel.ADD_USER -> controller.showAddUserDialog(null)
-                UserActionModel.ADD_SUPERVISED_USER -> controller.startSupervisedUserActivity()
-                UserActionModel.NAVIGATE_TO_USER_MANAGEMENT ->
-                    activityStarter.startActivity(
-                        Intent(Settings.ACTION_USER_SETTINGS),
-                        /* dismissShade= */ false,
-                    )
-            }
+            UserActionModel.ADD_SUPERVISED_USER ->
+                activityStarter.startActivity(
+                    Intent()
+                        .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
+                        .setPackage(supervisedUserPackageName)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                    /* dismissShade= */ true,
+                )
+            UserActionModel.NAVIGATE_TO_USER_MANAGEMENT ->
+                activityStarter.startActivity(
+                    Intent(Settings.ACTION_USER_SETTINGS),
+                    /* dismissShade= */ true,
+                )
         }
     }
 
@@ -757,6 +684,16 @@
         )
     }
 
+    private fun canCreateGuestUser(settings: UserSwitcherSettingsModel): Boolean {
+        return guestUserInteractor.isGuestUserAutoCreated ||
+            UserActionsUtil.canCreateGuest(
+                manager,
+                repository,
+                settings.isUserSwitcherEnabled,
+                settings.isAddUsersFromLockscreen,
+            )
+    }
+
     companion object {
         private const val TAG = "UserInteractor"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
index ad09ee3..e137107 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
@@ -133,7 +133,9 @@
                 launch {
                     viewModel.users.collect { users ->
                         val viewPool =
-                            view.children.filter { it.tag == USER_VIEW_TAG }.toMutableList()
+                            gridContainerView.children
+                                .filter { it.tag == USER_VIEW_TAG }
+                                .toMutableList()
                         viewPool.forEach {
                             gridContainerView.removeView(it)
                             flowWidget.removeView(it)
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
index e921720..58a4473 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
@@ -27,15 +27,12 @@
 import com.android.systemui.broadcast.BroadcastSender
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.user.domain.interactor.UserInteractor
 import com.android.systemui.user.domain.model.ShowDialogRequestModel
 import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.launch
 
@@ -50,16 +47,11 @@
     private val broadcastSender: Lazy<BroadcastSender>,
     private val dialogLaunchAnimator: Lazy<DialogLaunchAnimator>,
     private val interactor: Lazy<UserInteractor>,
-    private val featureFlags: Lazy<FeatureFlags>,
 ) : CoreStartable {
 
     private var currentDialog: Dialog? = null
 
     override fun start() {
-        if (featureFlags.get().isEnabled(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER)) {
-            return
-        }
-
         startHandlingDialogShowRequests()
         startHandlingDialogDismissRequests()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
index d857e85..0910ea3 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
@@ -20,8 +20,6 @@
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import com.android.systemui.common.ui.drawable.CircularDrawable
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.user.domain.interactor.GuestUserInteractor
 import com.android.systemui.user.domain.interactor.UserInteractor
@@ -41,12 +39,8 @@
     private val userInteractor: UserInteractor,
     private val guestUserInteractor: GuestUserInteractor,
     private val powerInteractor: PowerInteractor,
-    private val featureFlags: FeatureFlags,
 ) : ViewModel() {
 
-    private val isNewImpl: Boolean
-        get() = !featureFlags.isEnabled(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER)
-
     /** On-device users. */
     val users: Flow<List<UserViewModel>> =
         userInteractor.users.map { models -> models.map { user -> toViewModel(user) } }
@@ -216,7 +210,6 @@
         private val userInteractor: UserInteractor,
         private val guestUserInteractor: GuestUserInteractor,
         private val powerInteractor: PowerInteractor,
-        private val featureFlags: FeatureFlags,
     ) : ViewModelProvider.Factory {
         override fun <T : ViewModel> create(modelClass: Class<T>): T {
             @Suppress("UNCHECKED_CAST")
@@ -224,7 +217,6 @@
                 userInteractor = userInteractor,
                 guestUserInteractor = guestUserInteractor,
                 powerInteractor = powerInteractor,
-                featureFlags = featureFlags,
             )
                 as T
         }
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java b/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java
index d7c4e93..3c57081 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java
@@ -16,10 +16,11 @@
 
 package com.android.systemui.util.time;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.text.format.DateFormat;
 
+import com.android.systemui.settings.UserTracker;
+
 import javax.inject.Inject;
 
 /**
@@ -27,14 +28,16 @@
  */
 public class DateFormatUtil {
     private final Context mContext;
+    private final UserTracker mUserTracker;
 
     @Inject
-    public DateFormatUtil(Context context) {
+    public DateFormatUtil(Context context, UserTracker userTracker) {
         mContext = context;
+        mUserTracker = userTracker;
     }
 
     /** Returns true if the phone is in 24 hour format. */
     public boolean is24HourFormat() {
-        return DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());
+        return DateFormat.is24HourFormat(mContext, mUserTracker.getUserId());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 3094a8c..0d96272 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1228,6 +1228,9 @@
                 effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
                 break;
             case RINGER_MODE_VIBRATE:
+                // Feedback handled by onStateChange, for feedback both when user toggles
+                // directly in volume dialog, or drags slider to a value of 0 in settings.
+                break;
             default:
                 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
         }
@@ -1628,9 +1631,8 @@
                 && mState.ringerModeInternal != -1
                 && mState.ringerModeInternal != state.ringerModeInternal
                 && state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
-            mController.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK));
+            mController.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK));
         }
-
         mState = state;
         mDynamic.clear();
         // add any new dynamic rows
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index ea0b03d..78c28ea 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -140,6 +140,12 @@
             tools:replace="android:authorities"
             tools:node="remove" />
 
+        <provider android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
+            android:authorities="com.android.systemui.test.keyguard.quickaffordance.disabled"
+            android:enabled="false"
+            tools:replace="android:authorities"
+            tools:node="remove" />
+
         <provider
             android:name="androidx.core.content.FileProvider"
             android:authorities="com.android.systemui.test.fileprovider"
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 52b6b38..e8f8e25 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -155,7 +155,8 @@
         verify(configurationController).addCallback(capture(captor))
         captor.value.onDensityOrFontScaleChanged()
 
-        verify(events).onFontSettingChanged()
+        verify(smallClockEvents, times(2)).onFontSettingChanged(anyFloat())
+        verify(largeClockEvents, times(2)).onFontSettingChanged(anyFloat())
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index 131cf7d..8839662 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -84,10 +84,9 @@
     userId = user,
     listening = false,
     authInterruptActive = false,
-    becauseCannotSkipBouncer = false,
     biometricSettingEnabledForUser = false,
     bouncerFullyShown = false,
-    faceAuthenticated = false,
+    faceAndFpNotAuthenticated = false,
     faceDisabled = false,
     faceLockedOut = false,
     fpLockedOut = false,
@@ -101,4 +100,6 @@
     secureCameraLaunched = false,
     switchingUser = false,
     udfpsBouncerShowing = false,
+    udfpsFingerDown = false,
+    userNotTrustedOrDetectionIsNeeded = false
 )
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
index 5d2b0ca..8290084 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java
@@ -16,8 +16,11 @@
 
 package com.android.keyguard;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -90,4 +93,11 @@
         mMessageAreaController.setIsVisible(true);
         verify(mKeyguardMessageArea).setIsVisible(true);
     }
+
+    @Test
+    public void testGetMessage() {
+        String msg = "abc";
+        when(mKeyguardMessageArea.getText()).thenReturn(msg);
+        assertThat(mMessageAreaController.getMessage()).isEqualTo(msg);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index b369098..ffd95f4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -31,6 +31,7 @@
 import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.`when`
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
@@ -118,4 +119,14 @@
         keyguardPasswordViewController.startAppearAnimation()
         verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_password)
     }
+
+    @Test
+    fun startAppearAnimation_withExistingMessage() {
+        `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
+        keyguardPasswordViewController.startAppearAnimation()
+        verify(
+            mKeyguardMessageAreaController,
+            never()
+        ).setMessage(R.string.keyguard_enter_your_password)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index 9eff704..b3d1c8f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -33,6 +33,7 @@
 import org.mockito.Mock
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -112,4 +113,14 @@
         mKeyguardPatternViewController.startAppearAnimation()
         verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
     }
+
+    @Test
+    fun startAppearAnimation_withExistingMessage() {
+        `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
+        mKeyguardPatternViewController.startAppearAnimation()
+        verify(
+            mKeyguardMessageAreaController,
+            never()
+        ).setMessage(R.string.keyguard_enter_your_password)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index d9efdea..8bcfe6f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -100,4 +100,12 @@
         pinViewController.startAppearAnimation()
         verify(keyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pin)
     }
+
+    @Test
+    fun startAppearAnimation_withExistingMessage() {
+        Mockito.`when`(keyguardMessageAreaController.message).thenReturn("Unlock to continue.")
+        pinViewController.startAppearAnimation()
+        verify(keyguardMessageAreaController, Mockito.never())
+            .setMessage(R.string.keyguard_enter_your_password)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index aa4469f..4d58b09 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -548,6 +548,22 @@
         verify(mKeyguardPasswordViewControllerMock, never()).showMessage(null, null);
     }
 
+    @Test
+    public void onDensityorFontScaleChanged() {
+        ArgumentCaptor<ConfigurationController.ConfigurationListener>
+                configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
+                ConfigurationController.ConfigurationListener.class);
+        mKeyguardSecurityContainerController.onViewAttached();
+        verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
+        configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
+
+        verify(mView).onDensityOrFontScaleChanged();
+        verify(mKeyguardSecurityViewFlipperController).onDensityOrFontScaleChanged();
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
+                any(KeyguardSecurityCallback.class));
+    }
+
+
     private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 1bd14e5..36ed669 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -262,9 +262,12 @@
         ConstraintSet.Constraint userSwitcherConstraint =
                 getViewConstraint(R.id.keyguard_bouncer_user_switcher);
 
-        assertThat(viewFlipperConstraint.layout.topToTop).isEqualTo(PARENT_ID);
+        assertThat(viewFlipperConstraint.layout.topToBottom).isEqualTo(
+                R.id.keyguard_bouncer_user_switcher);
         assertThat(viewFlipperConstraint.layout.bottomToBottom).isEqualTo(PARENT_ID);
         assertThat(userSwitcherConstraint.layout.topToTop).isEqualTo(PARENT_ID);
+        assertThat(userSwitcherConstraint.layout.bottomToTop).isEqualTo(
+                mSecurityViewFlipper.getId());
         assertThat(userSwitcherConstraint.layout.topMargin).isEqualTo(
                 getContext().getResources().getDimensionPixelSize(
                         R.dimen.bouncer_user_switcher_y_trans));
@@ -308,6 +311,17 @@
     }
 
     @Test
+    public void testOnDensityOrFontScaleChanged() {
+        setupUserSwitcher();
+        View oldUserSwitcher = mKeyguardSecurityContainer.findViewById(
+                R.id.keyguard_bouncer_user_switcher);
+        mKeyguardSecurityContainer.onDensityOrFontScaleChanged();
+        View newUserSwitcher = mKeyguardSecurityContainer.findViewById(
+                R.id.keyguard_bouncer_user_switcher);
+        assertThat(oldUserSwitcher).isNotEqualTo(newUserSwitcher);
+    }
+
+    @Test
     public void testTouchesAreRecognizedAsBeingOnTheOtherSideOfSecurity() {
         setupUserSwitcher();
         setViewWidth(VIEW_WIDTH);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
index 9296d3d..fd02ac9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
@@ -106,4 +106,10 @@
             }
         }
     }
+
+    @Test
+    public void onDensityOrFontScaleChanged() {
+        mKeyguardSecurityViewFlipperController.onDensityOrFontScaleChanged();
+        verify(mView).removeAllViews();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index c6200da..beb9a72 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -28,6 +28,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
 import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
+import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -35,6 +36,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
@@ -88,6 +90,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.dreams.IDreamManager;
+import android.service.trust.TrustAgentService;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -112,6 +115,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -156,6 +160,8 @@
     private static final int FINGERPRINT_SENSOR_ID = 1;
 
     @Mock
+    private UserTracker mUserTracker;
+    @Mock
     private DumpManager mDumpManager;
     @Mock
     private KeyguardUpdateMonitor.StrongAuthTracker mStrongAuthTracker;
@@ -306,8 +312,7 @@
         ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                 .when(SubscriptionManager::getDefaultSubscriptionId);
         KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
-        ExtendedMockito.doReturn(KeyguardUpdateMonitor.getCurrentUser())
-                .when(ActivityManager::getCurrentUser);
+        when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
         ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
 
         mFaceWakeUpTriggersConfig = new FaceWakeUpTriggersConfig(
@@ -351,7 +356,9 @@
 
     @After
     public void tearDown() {
-        mMockitoSession.finishMocking();
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
         cleanupKeyguardUpdateMonitor();
     }
 
@@ -1032,6 +1039,7 @@
     @Test
     public void testSecondaryLockscreenRequirement() {
         KeyguardUpdateMonitor.setCurrentUser(UserHandle.myUserId());
+        when(mUserTracker.getUserId()).thenReturn(UserHandle.myUserId());
         int user = KeyguardUpdateMonitor.getCurrentUser();
         String packageName = "fake.test.package";
         String cls = "FakeService";
@@ -1314,7 +1322,10 @@
                 Arrays.asList("Unlocked by wearable"));
 
         // THEN the showTrustGrantedMessage should be called with the first message
-        verify(mTestCallback).showTrustGrantedMessage("Unlocked by wearable");
+        verify(mTestCallback).onTrustGrantedForCurrentUser(
+                anyBoolean(),
+                eq(new TrustGrantFlags(0)),
+                eq("Unlocked by wearable"));
     }
 
     @Test
@@ -1371,6 +1382,29 @@
     }
 
     @Test
+    public void testShouldListenForFace_whenFpIsAlreadyAuthenticated_returnsFalse()
+            throws RemoteException {
+        // Face auth should run when the following is true.
+        bouncerFullyVisibleAndNotGoingToSleep();
+        keyguardNotGoingAway();
+        currentUserIsPrimary();
+        strongAuthNotRequired();
+        biometricsEnabledForCurrentUser();
+        currentUserDoesNotHaveTrust();
+        biometricsNotDisabledThroughDevicePolicyManager();
+        userNotCurrentlySwitching();
+
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+
+        successfulFingerprintAuth();
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+    }
+
+    @Test
     public void testShouldListenForFace_whenUserIsNotPrimary_returnsFalse() throws RemoteException {
         cleanupKeyguardUpdateMonitor();
         // This disables face auth
@@ -1724,6 +1758,155 @@
         verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
     }
 
+
+    @Test
+    public void testOnTrustGrantedForCurrentUser_dismissKeyguardRequested_deviceInteractive() {
+        // GIVEN device is interactive
+        deviceIsInteractive();
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged with TRUST_DISMISS_KEYGUARD flag
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                getCurrentUser() /* userId */,
+                TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback).onTrustGrantedForCurrentUser(
+                eq(true) /* dismissKeyguard */,
+                eq(new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD)),
+                eq(null) /* message */
+        );
+    }
+
+    @Test
+    public void testOnTrustGrantedForCurrentUser_dismissKeyguardRequested_doesNotDismiss() {
+        // GIVEN device is NOT interactive
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged with TRUST_DISMISS_KEYGUARD flag
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                getCurrentUser() /* userId */,
+                TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback).onTrustGrantedForCurrentUser(
+                eq(false) /* dismissKeyguard */,
+                eq(new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD)),
+                eq(null) /* message */
+        );
+    }
+
+    @Test
+    public void testOnTrustGrantedForCurrentUser_dismissKeyguardRequested_temporaryAndRenewable() {
+        // GIVEN device is interactive
+        deviceIsInteractive();
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged for a different user
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                546 /* userId, not the current userId */,
+                0 /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback, never()).onTrustGrantedForCurrentUser(
+                anyBoolean() /* dismissKeyguard */,
+                anyObject() /* flags */,
+                anyString() /* message */
+        );
+    }
+
+    @Test
+    public void testOnTrustGranted_differentUser_noCallback() {
+        // GIVEN device is interactive
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged with TRUST_DISMISS_KEYGUARD AND TRUST_TEMPORARY_AND_RENEWABLE
+        // flags (temporary & rewable is active unlock)
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                getCurrentUser() /* userId */,
+                TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD
+                        | TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback).onTrustGrantedForCurrentUser(
+                eq(true) /* dismissKeyguard */,
+                eq(new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD
+                        | TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)),
+                eq(null) /* message */
+        );
+    }
+
+    @Test
+    public void testOnTrustGrantedForCurrentUser_bouncerShowing_initiatedByUser() {
+        // GIVEN device is interactive & bouncer is showing
+        deviceIsInteractive();
+        bouncerFullyVisible();
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged with INITIATED_BY_USER flag
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                getCurrentUser() /* userId, not the current userId */,
+                TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback, never()).onTrustGrantedForCurrentUser(
+                eq(true) /* dismissKeyguard */,
+                eq(new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER)),
+                anyString() /* message */
+        );
+    }
+
+    @Test
+    public void testOnTrustGrantedForCurrentUser_bouncerShowing_temporaryRenewable() {
+        // GIVEN device is NOT interactive & bouncer is showing
+        bouncerFullyVisible();
+
+        // GIVEN callback is registered
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN onTrustChanged with INITIATED_BY_USER flag
+        mKeyguardUpdateMonitor.onTrustChanged(
+                true /* enabled */,
+                getCurrentUser() /* userId, not the current userId */,
+                TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER
+                        | TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE /* flags */,
+                null /* trustGrantedMessages */);
+
+        // THEN onTrustGrantedForCurrentUser callback called
+        verify(callback, never()).onTrustGrantedForCurrentUser(
+                eq(true) /* dismissKeyguard */,
+                eq(new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER
+                        | TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)),
+                anyString() /* message */
+        );
+    }
+
     private void cleanupKeyguardUpdateMonitor() {
         if (mKeyguardUpdateMonitor != null) {
             mKeyguardUpdateMonitor.removeCallback(mTestCallback);
@@ -1775,6 +1958,15 @@
                 .onAuthenticationAcquired(FINGERPRINT_ACQUIRED_START);
     }
 
+    private void successfulFingerprintAuth() {
+        mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
+                .onAuthenticationSucceeded(
+                        new FingerprintManager.AuthenticationResult(null,
+                                null,
+                                mCurrentUserId,
+                                true));
+    }
+
     private void triggerSuccessfulFaceAuth() {
         mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
         verify(mFaceManager).authenticate(any(),
@@ -1884,7 +2076,7 @@
         AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
 
         protected TestableKeyguardUpdateMonitor(Context context) {
-            super(context,
+            super(context, mUserTracker,
                     TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
                     mBroadcastDispatcher, mSecureSettings, mDumpManager,
                     mBackgroundExecutor, mMainExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index ff4412e9..27701be 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -17,6 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -30,15 +31,15 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
 
-import androidx.lifecycle.MutableLiveData;
-
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerFake;
 import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.settings.CurrentUserObservable;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.After;
 import org.junit.Before;
@@ -52,8 +53,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-// Need to run tests on main looper because LiveData operations such as setData, observe,
-// removeObserver cannot be invoked on a background thread.
+// Need to run tests on main looper to allow for onClockChanged operation to happen synchronously.
 @RunWithLooper(setAsMainLooper = true)
 public final class ClockManagerTest extends SysuiTestCase {
 
@@ -63,14 +63,16 @@
     private static final int SECONDARY_USER_ID = 11;
     private static final Uri SETTINGS_URI = null;
 
+    private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
+    private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
     private ClockManager mClockManager;
     private ContentObserver mContentObserver;
     private DockManagerFake mFakeDockManager;
-    private MutableLiveData<Integer> mCurrentUser;
+    private ArgumentCaptor<UserTracker.Callback> mUserTrackerCallbackCaptor;
     @Mock PluginManager mMockPluginManager;
     @Mock SysuiColorExtractor mMockColorExtractor;
     @Mock ContentResolver mMockContentResolver;
-    @Mock CurrentUserObservable mMockCurrentUserObserable;
+    @Mock UserTracker mUserTracker;
     @Mock SettingsWrapper mMockSettingsWrapper;
     @Mock ClockManager.ClockChangedListener mMockListener1;
     @Mock ClockManager.ClockChangedListener mMockListener2;
@@ -83,18 +85,18 @@
 
         mFakeDockManager = new DockManagerFake();
 
-        mCurrentUser = new MutableLiveData<>();
-        mCurrentUser.setValue(MAIN_USER_ID);
-        when(mMockCurrentUserObserable.getCurrentUser()).thenReturn(mCurrentUser);
+        when(mUserTracker.getUserId()).thenReturn(MAIN_USER_ID);
+        mUserTrackerCallbackCaptor = ArgumentCaptor.forClass(UserTracker.Callback.class);
 
         mClockManager = new ClockManager(getContext(), inflater,
                 mMockPluginManager, mMockColorExtractor, mMockContentResolver,
-                mMockCurrentUserObserable, mMockSettingsWrapper, mFakeDockManager);
+                mUserTracker, mMainExecutor, mMockSettingsWrapper, mFakeDockManager);
 
         mClockManager.addBuiltinClock(() -> new BubbleClockController(
                 getContext().getResources(), inflater, mMockColorExtractor));
         mClockManager.addOnClockChangedListener(mMockListener1);
         mClockManager.addOnClockChangedListener(mMockListener2);
+        verify(mUserTracker).addCallback(mUserTrackerCallbackCaptor.capture(), any());
         reset(mMockListener1, mMockListener2);
 
         mContentObserver = mClockManager.getContentObserver();
@@ -221,7 +223,7 @@
     @Test
     public void onUserChanged_defaultClock() {
         // WHEN the user changes
-        mCurrentUser.setValue(SECONDARY_USER_ID);
+        switchUser(SECONDARY_USER_ID);
         // THEN the plugin is null for the default clock face
         assertThat(mClockManager.getCurrentClock()).isNull();
     }
@@ -232,7 +234,7 @@
         when(mMockSettingsWrapper.getLockScreenCustomClockFace(SECONDARY_USER_ID)).thenReturn(
                 BUBBLE_CLOCK);
         // WHEN the user changes
-        mCurrentUser.setValue(SECONDARY_USER_ID);
+        switchUser(SECONDARY_USER_ID);
         // THEN the plugin is the bubble clock face.
         assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS);
     }
@@ -244,8 +246,13 @@
         // AND the second user as selected the bubble clock for the dock
         when(mMockSettingsWrapper.getDockedClockFace(SECONDARY_USER_ID)).thenReturn(BUBBLE_CLOCK);
         // WHEN the user changes
-        mCurrentUser.setValue(SECONDARY_USER_ID);
+        switchUser(SECONDARY_USER_ID);
         // THEN the plugin is the bubble clock face.
         assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS);
     }
+
+    private void switchUser(int newUser) {
+        when(mUserTracker.getUserId()).thenReturn(newUser);
+        mUserTrackerCallbackCaptor.getValue().onUserChanged(newUser, mContext);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
index a4e0825..5886206 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui
 
+import android.content.Context
 import android.graphics.Canvas
 import android.graphics.Insets
 import android.graphics.Path
@@ -48,6 +49,7 @@
     @Mock private lateinit var mockCanvas: Canvas
     @Mock private lateinit var mockRootView: View
     @Mock private lateinit var mockDisplay: Display
+    @Mock private lateinit var mockContext: Context
 
     private lateinit var cutoutBaseView: DisplayCutoutBaseView
     private val cutout: DisplayCutout = DisplayCutout.Builder()
@@ -168,7 +170,9 @@
                 R.bool.config_fillMainBuiltInDisplayCutout, fillCutout)
 
         cutoutBaseView = spy(DisplayCutoutBaseView(mContext))
-        whenever(cutoutBaseView.display).thenReturn(mockDisplay)
+
+        whenever(cutoutBaseView.context).thenReturn(mockContext)
+        whenever(mockContext.display).thenReturn(mockDisplay)
         whenever(mockDisplay.uniqueId).thenReturn("mockDisplayUniqueId")
         whenever(cutoutBaseView.rootView).thenReturn(mockRootView)
         whenever(cutoutBaseView.getPhysicalPixelDisplaySizeRatio()).thenReturn(1f)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
index 054650b..8207fa6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui
 
+import android.content.Context
 import android.graphics.Insets
 import android.graphics.PixelFormat
 import android.graphics.Rect
@@ -44,6 +45,7 @@
 
     @Mock private lateinit var mockDisplay: Display
     @Mock private lateinit var mockRootView: View
+    @Mock private lateinit var mockContext: Context
 
     private val displayWidth = 100
     private val displayHeight = 200
@@ -75,7 +77,8 @@
         decorHwcLayer = Mockito.spy(ScreenDecorHwcLayer(mContext, decorationSupport))
         whenever(decorHwcLayer.width).thenReturn(displayWidth)
         whenever(decorHwcLayer.height).thenReturn(displayHeight)
-        whenever(decorHwcLayer.display).thenReturn(mockDisplay)
+        whenever(decorHwcLayer.context).thenReturn(mockContext)
+        whenever(mockContext.display).thenReturn(mockDisplay)
         whenever(decorHwcLayer.rootView).thenReturn(mockRootView)
         whenever(mockRootView.left).thenReturn(0)
         whenever(mockRootView.top).thenReturn(0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt
new file mode 100644
index 0000000..982f033
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.battery
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@SmallTest
+class AccessorizedBatteryDrawableTest : SysuiTestCase() {
+    @Test
+    fun intrinsicSize_shieldFalse_isBatterySize() {
+        val drawable = AccessorizedBatteryDrawable(context, frameColor = 0)
+        drawable.displayShield = false
+
+        val density = context.resources.displayMetrics.density
+        assertThat(drawable.intrinsicHeight).isEqualTo((BATTERY_HEIGHT * density).toInt())
+        assertThat(drawable.intrinsicWidth).isEqualTo((BATTERY_WIDTH * density).toInt())
+    }
+
+    @Test
+    fun intrinsicSize_shieldTrue_isBatteryPlusShieldSize() {
+        val drawable = AccessorizedBatteryDrawable(context, frameColor = 0)
+        drawable.displayShield = true
+
+        val density = context.resources.displayMetrics.density
+        assertThat(drawable.intrinsicHeight)
+            .isEqualTo((BATTERY_HEIGHT_WITH_SHIELD * density).toInt())
+        assertThat(drawable.intrinsicWidth).isEqualTo((BATTERY_WIDTH_WITH_SHIELD * density).toInt())
+    }
+
+    // TODO(b/255625888): Screenshot tests for this drawable would be amazing!
+}
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 1d038a4..1482f29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -34,7 +34,9 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.tuner.TunerService;
@@ -50,15 +52,16 @@
     private BatteryMeterView mBatteryMeterView;
 
     @Mock
+    private UserTracker mUserTracker;
+    @Mock
     private ConfigurationController mConfigurationController;
     @Mock
     private TunerService mTunerService;
     @Mock
-    private BroadcastDispatcher mBroadcastDispatcher;
-    @Mock
     private Handler mHandler;
     @Mock
     private ContentResolver mContentResolver;
+    private FakeFeatureFlags mFeatureFlags;
     @Mock
     private BatteryController mBatteryController;
 
@@ -71,19 +74,13 @@
         when(mBatteryMeterView.getContext()).thenReturn(mContext);
         when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
 
-        mController = new BatteryMeterViewController(
-                mBatteryMeterView,
-                mConfigurationController,
-                mTunerService,
-                mBroadcastDispatcher,
-                mHandler,
-                mContentResolver,
-                mBatteryController
-        );
+        mFeatureFlags = new FakeFeatureFlags();
+        mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
     }
 
     @Test
     public void onViewAttached_callbacksRegistered() {
+        initController();
         mController.onViewAttached();
 
         verify(mConfigurationController).addCallback(any());
@@ -101,6 +98,7 @@
 
     @Test
     public void onViewDetached_callbacksUnregistered() {
+        initController();
         // Set everything up first.
         mController.onViewAttached();
 
@@ -114,6 +112,7 @@
 
     @Test
     public void ignoreTunerUpdates_afterOnViewAttached_callbackUnregistered() {
+        initController();
         // Start out receiving tuner updates
         mController.onViewAttached();
 
@@ -124,10 +123,43 @@
 
     @Test
     public void ignoreTunerUpdates_beforeOnViewAttached_callbackNeverRegistered() {
+        initController();
+
         mController.ignoreTunerUpdates();
 
         mController.onViewAttached();
 
         verify(mTunerService, never()).addTunable(any(), any());
     }
+
+    @Test
+    public void shieldFlagDisabled_viewNotified() {
+        mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
+
+        initController();
+
+        verify(mBatteryMeterView).setDisplayShieldEnabled(false);
+    }
+
+    @Test
+    public void shieldFlagEnabled_viewNotified() {
+        mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, true);
+
+        initController();
+
+        verify(mBatteryMeterView).setDisplayShieldEnabled(true);
+    }
+
+    private void initController() {
+        mController = new BatteryMeterViewController(
+                mBatteryMeterView,
+                mUserTracker,
+                mConfigurationController,
+                mTunerService,
+                mHandler,
+                mContentResolver,
+                mFeatureFlags,
+                mBatteryController
+        );
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
index b4ff2a5..eb7d9c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
@@ -17,7 +17,9 @@
 
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
+import android.widget.ImageView
 import androidx.test.filters.SmallTest
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
 import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
@@ -58,6 +60,182 @@
         // No assert needed
     }
 
+    @Test
+    fun contentDescription_unknown() {
+        mBatteryMeterView.onBatteryUnknownStateChanged(true)
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_unknown)
+        )
+    }
+
+    @Test
+    fun contentDescription_estimate() {
+        mBatteryMeterView.onBatteryLevelChanged(15, false)
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+        mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
+
+        mBatteryMeterView.updatePercentText()
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(
+                        R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
+                )
+        )
+    }
+
+    @Test
+    fun contentDescription_estimateAndOverheated() {
+        mBatteryMeterView.onBatteryLevelChanged(17, false)
+        mBatteryMeterView.onIsOverheatedChanged(true)
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+        mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
+
+        mBatteryMeterView.updatePercentText()
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(
+                        R.string.accessibility_battery_level_charging_paused_with_estimate,
+                        17,
+                        ESTIMATE,
+                )
+        )
+    }
+
+    @Test
+    fun contentDescription_overheated() {
+        mBatteryMeterView.onBatteryLevelChanged(90, false)
+        mBatteryMeterView.onIsOverheatedChanged(true)
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level_charging_paused, 90)
+        )
+    }
+
+    @Test
+    fun contentDescription_charging() {
+        mBatteryMeterView.onBatteryLevelChanged(45, true)
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level_charging, 45)
+        )
+    }
+
+    @Test
+    fun contentDescription_notCharging() {
+        mBatteryMeterView.onBatteryLevelChanged(45, false)
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level, 45)
+        )
+    }
+
+    @Test
+    fun changesFromEstimateToPercent_textAndContentDescriptionChanges() {
+        mBatteryMeterView.onBatteryLevelChanged(15, false)
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+        mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
+
+        mBatteryMeterView.updatePercentText()
+
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(
+                        R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
+                )
+        )
+
+        // Update the show mode from estimate to percent
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
+
+        assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo("15%")
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level, 15)
+        )
+    }
+
+    @Test
+    fun contentDescription_manyUpdates_alwaysUpdated() {
+        // Overheated
+        mBatteryMeterView.onBatteryLevelChanged(90, false)
+        mBatteryMeterView.onIsOverheatedChanged(true)
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level_charging_paused, 90)
+        )
+
+        // Overheated & estimate
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
+        mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
+        mBatteryMeterView.updatePercentText()
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(
+                        R.string.accessibility_battery_level_charging_paused_with_estimate,
+                        90,
+                        ESTIMATE,
+                )
+        )
+
+        // Just estimate
+        mBatteryMeterView.onIsOverheatedChanged(false)
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(
+                        R.string.accessibility_battery_level_with_estimate,
+                        90,
+                        ESTIMATE,
+                )
+        )
+
+        // Just percent
+        mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level, 90)
+        )
+
+        // Charging
+        mBatteryMeterView.onBatteryLevelChanged(90, true)
+        assertThat(mBatteryMeterView.contentDescription).isEqualTo(
+                context.getString(R.string.accessibility_battery_level_charging, 90)
+        )
+    }
+
+    @Test
+    fun isOverheatedChanged_true_drawableGetsTrue() {
+        mBatteryMeterView.setDisplayShieldEnabled(true)
+        val drawable = getBatteryDrawable()
+
+        mBatteryMeterView.onIsOverheatedChanged(true)
+
+        assertThat(drawable.displayShield).isTrue()
+    }
+
+    @Test
+    fun isOverheatedChanged_false_drawableGetsFalse() {
+        mBatteryMeterView.setDisplayShieldEnabled(true)
+        val drawable = getBatteryDrawable()
+
+        // Start as true
+        mBatteryMeterView.onIsOverheatedChanged(true)
+
+        // Update to false
+        mBatteryMeterView.onIsOverheatedChanged(false)
+
+        assertThat(drawable.displayShield).isFalse()
+    }
+
+    @Test
+    fun isOverheatedChanged_true_featureflagOff_drawableGetsFalse() {
+        mBatteryMeterView.setDisplayShieldEnabled(false)
+        val drawable = getBatteryDrawable()
+
+        mBatteryMeterView.onIsOverheatedChanged(true)
+
+        assertThat(drawable.displayShield).isFalse()
+    }
+
+    private fun getBatteryDrawable(): AccessorizedBatteryDrawable {
+        return (mBatteryMeterView.getChildAt(0) as ImageView)
+                .drawable as AccessorizedBatteryDrawable
+    }
+
     private class Fetcher : BatteryEstimateFetcher {
         override fun fetchBatteryTimeRemainingEstimate(
                 completion: EstimateFetchCompletion) {
@@ -68,4 +246,4 @@
     private companion object {
         const val ESTIMATE = "2 hours 2 minutes"
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt
new file mode 100644
index 0000000..39cb047
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.battery
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
+import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
+import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@SmallTest
+class BatterySpecsTest : SysuiTestCase() {
+    @Test
+    fun getFullBatteryHeight_shieldFalse_returnsMainHeight() {
+        val fullHeight = BatterySpecs.getFullBatteryHeight(56f, displayShield = false)
+
+        assertThat(fullHeight).isEqualTo(56f)
+    }
+
+    @Test
+    fun getFullBatteryHeight_shieldTrue_returnsMainHeightPlusShield() {
+        val mainHeight = BATTERY_HEIGHT * 5
+        val fullHeight = BatterySpecs.getFullBatteryHeight(mainHeight, displayShield = true)
+
+        // Since the main battery was scaled 5x, the output height should also be scaled 5x
+        val expectedFullHeight = BATTERY_HEIGHT_WITH_SHIELD * 5
+
+        assertThat(fullHeight).isWithin(.0001f).of(expectedFullHeight)
+    }
+
+    @Test
+    fun getFullBatteryWidth_shieldFalse_returnsMainWidth() {
+        val fullWidth = BatterySpecs.getFullBatteryWidth(33f, displayShield = false)
+
+        assertThat(fullWidth).isEqualTo(33f)
+    }
+
+    @Test
+    fun getFullBatteryWidth_shieldTrue_returnsMainWidthPlusShield() {
+        val mainWidth = BATTERY_WIDTH * 3.3f
+
+        val fullWidth = BatterySpecs.getFullBatteryWidth(mainWidth, displayShield = true)
+
+        // Since the main battery was scaled 3.3x, the output width should also be scaled 5x
+        val expectedFullWidth = BATTERY_WIDTH_WITH_SHIELD * 3.3f
+        assertThat(fullWidth).isWithin(.0001f).of(expectedFullWidth)
+    }
+
+    @Test
+    fun getMainBatteryHeight_shieldFalse_returnsFullHeight() {
+        val mainHeight = BatterySpecs.getMainBatteryHeight(89f, displayShield = false)
+
+        assertThat(mainHeight).isEqualTo(89f)
+    }
+
+    @Test
+    fun getMainBatteryHeight_shieldTrue_returnsNotFullHeight() {
+        val fullHeight = BATTERY_HEIGHT_WITH_SHIELD * 7.7f
+
+        val mainHeight = BatterySpecs.getMainBatteryHeight(fullHeight, displayShield = true)
+
+        // Since the full height was scaled 7.7x, the main height should also be scaled 7.7x.
+        val expectedHeight = BATTERY_HEIGHT * 7.7f
+        assertThat(mainHeight).isWithin(.0001f).of(expectedHeight)
+    }
+
+    @Test
+    fun getMainBatteryWidth_shieldFalse_returnsFullWidth() {
+        val mainWidth = BatterySpecs.getMainBatteryWidth(2345f, displayShield = false)
+
+        assertThat(mainWidth).isEqualTo(2345f)
+    }
+
+    @Test
+    fun getMainBatteryWidth_shieldTrue_returnsNotFullWidth() {
+        val fullWidth = BATTERY_WIDTH_WITH_SHIELD * 0.6f
+
+        val mainWidth = BatterySpecs.getMainBatteryWidth(fullWidth, displayShield = true)
+
+        // Since the full width was scaled 0.6x, the main height should also be scaled 0.6x.
+        val expectedWidth = BATTERY_WIDTH * 0.6f
+        assertThat(mainWidth).isWithin(.0001f).of(expectedWidth)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 1b5f9b6..acdafe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -114,10 +114,8 @@
 
     @Rule
     public MockitoRule rule = MockitoJUnit.rule();
-
     // Unit under test
     private UdfpsController mUdfpsController;
-
     // Dependencies
     private FakeExecutor mBiometricsExecutor;
     @Mock
@@ -171,7 +169,6 @@
     private UdfpsDisplayMode mUdfpsDisplayMode;
     @Mock
     private FeatureFlags mFeatureFlags;
-
     // Stuff for configuring mocks
     @Mock
     private UdfpsView mUdfpsView;
@@ -249,54 +246,42 @@
                 FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC,
                 true /* resetLockoutRequiresHardwareAuthToken */);
 
-        List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
-        props.add(mOpticalProps);
-        props.add(mUltrasonicProps);
-        when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
-
         mFgExecutor = new FakeExecutor(new FakeSystemClock());
 
         // Create a fake background executor.
         mBiometricsExecutor = new FakeExecutor(new FakeSystemClock());
 
-        mUdfpsController = new UdfpsController(
-                mContext,
-                execution,
-                mLayoutInflater,
-                mFingerprintManager,
-                mWindowManager,
-                mStatusBarStateController,
-                mFgExecutor,
-                new ShadeExpansionStateManager(),
-                mStatusBarKeyguardViewManager,
-                mDumpManager,
-                mKeyguardUpdateMonitor,
-                mFeatureFlags,
-                mFalsingManager,
-                mPowerManager,
-                mAccessibilityManager,
-                mLockscreenShadeTransitionController,
-                mScreenLifecycle,
-                mVibrator,
-                mUdfpsHapticsSimulator,
-                mUdfpsShell,
-                mKeyguardStateController,
-                mDisplayManager,
-                mHandler,
-                mConfigurationController,
-                mSystemClock,
-                mUnlockedScreenOffAnimationController,
-                mSystemUIDialogManager,
-                mLatencyTracker,
-                mActivityLaunchAnimator,
-                Optional.of(mAlternateTouchProvider),
-                mBiometricsExecutor,
+        initUdfpsController(true /* hasAlternateTouchProvider */);
+    }
+
+    private void initUdfpsController(boolean hasAlternateTouchProvider) {
+        initUdfpsController(mOpticalProps, hasAlternateTouchProvider);
+    }
+
+    private void initUdfpsController(FingerprintSensorPropertiesInternal sensorProps,
+            boolean hasAlternateTouchProvider) {
+        reset(mFingerprintManager);
+        reset(mScreenLifecycle);
+
+        final Optional<AlternateUdfpsTouchProvider> alternateTouchProvider =
+                hasAlternateTouchProvider ? Optional.of(mAlternateTouchProvider) : Optional.empty();
+
+        mUdfpsController = new UdfpsController(mContext, new FakeExecution(), mLayoutInflater,
+                mFingerprintManager, mWindowManager, mStatusBarStateController, mFgExecutor,
+                new ShadeExpansionStateManager(), mStatusBarKeyguardViewManager, mDumpManager,
+                mKeyguardUpdateMonitor, mFeatureFlags, mFalsingManager, mPowerManager,
+                mAccessibilityManager, mLockscreenShadeTransitionController, mScreenLifecycle,
+                mVibrator, mUdfpsHapticsSimulator, mUdfpsShell, mKeyguardStateController,
+                mDisplayManager, mHandler, mConfigurationController, mSystemClock,
+                mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker,
+                mActivityLaunchAnimator, alternateTouchProvider, mBiometricsExecutor,
                 mPrimaryBouncerInteractor);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
         mScreenObserver = mScreenObserverCaptor.getValue();
-        mUdfpsController.updateOverlayParams(mOpticalProps, new UdfpsOverlayParams());
+
+        mUdfpsController.updateOverlayParams(sensorProps, new UdfpsOverlayParams());
         mUdfpsController.setUdfpsDisplayMode(mUdfpsDisplayMode);
     }
 
@@ -333,8 +318,7 @@
     }
 
     @Test
-    public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice()
-            throws RemoteException {
+    public void onActionMoveTouch_whenCanDismissLockScreen_entersDevice() throws RemoteException {
         onActionMoveTouch_whenCanDismissLockScreen_entersDevice(false /* stale */);
     }
 
@@ -521,8 +505,37 @@
                 new MotionEvent.PointerCoords[]{pc}, 0, 0, 1f, 1f, 0, 0, 0, 0);
     }
 
+    private static class TestParams {
+        public final FingerprintSensorPropertiesInternal sensorProps;
+        public final boolean hasAlternateTouchProvider;
+
+        TestParams(FingerprintSensorPropertiesInternal sensorProps,
+                boolean hasAlternateTouchProvider) {
+            this.sensorProps = sensorProps;
+            this.hasAlternateTouchProvider = hasAlternateTouchProvider;
+        }
+    }
+
+    private void runWithAllParams(ThrowingConsumer<TestParams> testParamsConsumer) {
+        for (FingerprintSensorPropertiesInternal sensorProps : List.of(mOpticalProps,
+                mUltrasonicProps)) {
+            for (boolean hasAlternateTouchProvider : new boolean[]{false, true}) {
+                initUdfpsController(sensorProps, hasAlternateTouchProvider);
+                testParamsConsumer.accept(new TestParams(sensorProps, hasAlternateTouchProvider));
+            }
+        }
+    }
+
     @Test
-    public void onTouch_propagatesTouchInNativeOrientationAndResolution() throws RemoteException {
+    public void onTouch_propagatesTouchInNativeOrientationAndResolution() {
+        runWithAllParams(
+                this::onTouch_propagatesTouchInNativeOrientationAndResolutionParameterized);
+    }
+
+    private void onTouch_propagatesTouchInNativeOrientationAndResolutionParameterized(
+            TestParams testParams) throws RemoteException {
+        reset(mUdfpsView);
+
         final Rect sensorBounds = new Rect(1000, 1900, 1080, 1920); // Bottom right corner.
         final int displayWidth = 1080;
         final int displayHeight = 1920;
@@ -541,13 +554,13 @@
         when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
 
         // Show the overlay.
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
 
         // Test ROTATION_0
-        mUdfpsController.updateOverlayParams(mOpticalProps,
+        mUdfpsController.updateOverlayParams(testParams.sensorProps,
                 new UdfpsOverlayParams(sensorBounds, sensorBounds, displayWidth, displayHeight,
                         scaleFactor, Surface.ROTATION_0));
         MotionEvent event = obtainMotionEvent(ACTION_DOWN, displayWidth, displayHeight, touchMinor,
@@ -559,12 +572,19 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
         mBiometricsExecutor.runAllReady();
         event.recycle();
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
-                eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
+                    eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(expectedX), eq(expectedY),
+                    eq(expectedMinor), eq(expectedMajor));
+        }
 
         // Test ROTATION_90
         reset(mAlternateTouchProvider);
-        mUdfpsController.updateOverlayParams(mOpticalProps,
+        reset(mFingerprintManager);
+        mUdfpsController.updateOverlayParams(testParams.sensorProps,
                 new UdfpsOverlayParams(sensorBounds, sensorBounds, displayWidth, displayHeight,
                         scaleFactor, Surface.ROTATION_90));
         event = obtainMotionEvent(ACTION_DOWN, displayHeight, 0, touchMinor, touchMajor);
@@ -575,12 +595,19 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
         mBiometricsExecutor.runAllReady();
         event.recycle();
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
-                eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
+                    eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(expectedX), eq(expectedY),
+                    eq(expectedMinor), eq(expectedMajor));
+        }
 
         // Test ROTATION_270
         reset(mAlternateTouchProvider);
-        mUdfpsController.updateOverlayParams(mOpticalProps,
+        reset(mFingerprintManager);
+        mUdfpsController.updateOverlayParams(testParams.sensorProps,
                 new UdfpsOverlayParams(sensorBounds, sensorBounds, displayWidth, displayHeight,
                         scaleFactor, Surface.ROTATION_270));
         event = obtainMotionEvent(ACTION_DOWN, 0, displayWidth, touchMinor, touchMajor);
@@ -591,12 +618,19 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
         mBiometricsExecutor.runAllReady();
         event.recycle();
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
-                eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
+                    eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(expectedX), eq(expectedY),
+                    eq(expectedMinor), eq(expectedMajor));
+        }
 
         // Test ROTATION_180
         reset(mAlternateTouchProvider);
-        mUdfpsController.updateOverlayParams(mOpticalProps,
+        reset(mFingerprintManager);
+        mUdfpsController.updateOverlayParams(testParams.sensorProps,
                 new UdfpsOverlayParams(sensorBounds, sensorBounds, displayWidth, displayHeight,
                         scaleFactor, Surface.ROTATION_180));
         // ROTATION_180 is not supported. It should be treated like ROTATION_0.
@@ -608,26 +642,22 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
         mBiometricsExecutor.runAllReady();
         event.recycle();
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
-                eq(expectedY), eq(expectedMinor), eq(expectedMajor));
-    }
-
-    private void runForAllUdfpsTypes(
-            ThrowingConsumer<FingerprintSensorPropertiesInternal> sensorPropsConsumer) {
-        for (FingerprintSensorPropertiesInternal sensorProps : List.of(mOpticalProps,
-                mUltrasonicProps)) {
-            mUdfpsController.updateOverlayParams(sensorProps, new UdfpsOverlayParams());
-            sensorPropsConsumer.accept(sensorProps);
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(expectedX),
+                    eq(expectedY), eq(expectedMinor), eq(expectedMajor));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(expectedX), eq(expectedY),
+                    eq(expectedMinor), eq(expectedMajor));
         }
     }
 
     @Test
     public void fingerDown() {
-        runForAllUdfpsTypes(this::fingerDownForSensor);
+        runWithAllParams(this::fingerDownParameterized);
     }
 
-    private void fingerDownForSensor(FingerprintSensorPropertiesInternal sensorProps)
-            throws RemoteException {
+    private void fingerDownParameterized(TestParams testParams) throws RemoteException {
         reset(mUdfpsView, mAlternateTouchProvider, mFingerprintManager, mLatencyTracker,
                 mKeyguardUpdateMonitor);
 
@@ -637,7 +667,7 @@
         when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
 
         // GIVEN that the overlay is showing
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -655,14 +685,22 @@
 
         mFgExecutor.runAllReady();
 
-        // THEN FingerprintManager is notified about onPointerDown
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(0f),
-                eq(0f));
-        verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(),
-                anyFloat(), anyFloat());
+        // THEN the touch provider is notified about onPointerDown.
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(0f),
+                    eq(0f));
+            verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(),
+                    anyInt(), anyFloat(), anyFloat());
+            verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(0), eq(0), eq(0f), eq(0f));
+            verify(mAlternateTouchProvider, never()).onPointerDown(anyInt(), anyInt(), anyInt(),
+                    anyFloat(), anyFloat());
+        }
 
         // AND display configuration begins
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             verify(mLatencyTracker).onActionStart(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
             verify(mUdfpsView).configureDisplay(mOnDisplayConfiguredCaptor.capture());
         } else {
@@ -671,16 +709,27 @@
             verify(mUdfpsView, never()).configureDisplay(any());
         }
         verify(mLatencyTracker, never()).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
-        verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // AND onDisplayConfigured notifies FingerprintManager about onUiReady
             mOnDisplayConfiguredCaptor.getValue().run();
             mBiometricsExecutor.runAllReady();
-            InOrder inOrder = inOrder(mAlternateTouchProvider, mLatencyTracker);
-            inOrder.verify(mAlternateTouchProvider).onUiReady();
-            inOrder.verify(mLatencyTracker).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
+            if (testParams.hasAlternateTouchProvider) {
+                InOrder inOrder = inOrder(mAlternateTouchProvider, mLatencyTracker);
+                inOrder.verify(mAlternateTouchProvider).onUiReady();
+                inOrder.verify(mLatencyTracker).onActionEnd(
+                        eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
+                verify(mFingerprintManager, never()).onUiReady(anyLong(), anyInt());
+            } else {
+                InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker);
+                inOrder.verify(mFingerprintManager).onUiReady(eq(TEST_REQUEST_ID),
+                        eq(testParams.sensorProps.sensorId));
+                inOrder.verify(mLatencyTracker).onActionEnd(
+                        eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
+                verify(mAlternateTouchProvider, never()).onUiReady();
+            }
         } else {
+            verify(mFingerprintManager, never()).onUiReady(anyLong(), anyInt());
             verify(mAlternateTouchProvider, never()).onUiReady();
             verify(mLatencyTracker, never()).onActionEnd(
                     eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
@@ -689,24 +738,23 @@
 
     @Test
     public void aodInterrupt() {
-        runForAllUdfpsTypes(this::aodInterruptForSensor);
+        runWithAllParams(this::aodInterruptParameterized);
     }
 
-    private void aodInterruptForSensor(FingerprintSensorPropertiesInternal sensorProps)
-            throws RemoteException {
+    private void aodInterruptParameterized(TestParams testParams) throws RemoteException {
         mUdfpsController.cancelAodInterrupt();
         reset(mUdfpsView, mAlternateTouchProvider, mFingerprintManager, mKeyguardUpdateMonitor);
         when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
 
         // GIVEN that the overlay is showing and screen is on and fp is running
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         // WHEN fingerprint is requested because of AOD interrupt
         mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
         mFgExecutor.runAllReady();
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // THEN display configuration begins
             // AND onDisplayConfigured notifies FingerprintManager about onUiReady
             verify(mUdfpsView).configureDisplay(mOnDisplayConfiguredCaptor.capture());
@@ -715,29 +763,37 @@
             verify(mUdfpsView, never()).configureDisplay(mOnDisplayConfiguredCaptor.capture());
         }
         mBiometricsExecutor.runAllReady();
-        verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID),
-                eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */);
-        verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(),
-                anyFloat(), anyFloat());
-        verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
+
+        if (testParams.hasAlternateTouchProvider) {
+            verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0),
+                    eq(3f) /* minor */, eq(2f) /* major */);
+            verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(),
+                    anyInt(), anyFloat(), anyFloat());
+            verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
+        } else {
+            verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
+                    eq(testParams.sensorProps.sensorId), eq(0), eq(0), eq(3f) /* minor */,
+                    eq(2f) /* major */);
+            verify(mAlternateTouchProvider, never()).onPointerDown(anyLong(), anyInt(), anyInt(),
+                    anyFloat(), anyFloat());
+        }
     }
 
     @Test
     public void cancelAodInterrupt() {
-        runForAllUdfpsTypes(this::cancelAodInterruptForSensor);
+        runWithAllParams(this::cancelAodInterruptParameterized);
     }
 
-    private void cancelAodInterruptForSensor(FingerprintSensorPropertiesInternal sensorProps)
-            throws RemoteException {
+    private void cancelAodInterruptParameterized(TestParams testParams) throws RemoteException {
         reset(mUdfpsView);
 
         // GIVEN AOD interrupt
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
             // WHEN it is cancelled
             mUdfpsController.cancelAodInterrupt();
@@ -754,21 +810,20 @@
 
     @Test
     public void aodInterruptTimeout() {
-        runForAllUdfpsTypes(this::aodInterruptTimeoutForSensor);
+        runWithAllParams(this::aodInterruptTimeoutParameterized);
     }
 
-    private void aodInterruptTimeoutForSensor(FingerprintSensorPropertiesInternal sensorProps)
-            throws RemoteException {
+    private void aodInterruptTimeoutParameterized(TestParams testParams) throws RemoteException {
         reset(mUdfpsView);
 
         // GIVEN AOD interrupt
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         mFgExecutor.runAllReady();
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
         } else {
             when(mUdfpsView.isDisplayConfigured()).thenReturn(false);
@@ -776,7 +831,7 @@
         // WHEN it times out
         mFgExecutor.advanceClockToNext();
         mFgExecutor.runAllReady();
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // THEN the display is unconfigured.
             verify(mUdfpsView).unconfigureDisplay();
         } else {
@@ -787,23 +842,23 @@
 
     @Test
     public void aodInterruptCancelTimeoutActionOnFingerUp() {
-        runForAllUdfpsTypes(this::aodInterruptCancelTimeoutActionOnFingerUpForSensor);
+        runWithAllParams(this::aodInterruptCancelTimeoutActionOnFingerUpParameterized);
     }
 
-    private void aodInterruptCancelTimeoutActionOnFingerUpForSensor(
-            FingerprintSensorPropertiesInternal sensorProps) throws RemoteException {
+    private void aodInterruptCancelTimeoutActionOnFingerUpParameterized(TestParams testParams)
+            throws RemoteException {
         reset(mUdfpsView);
         when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
 
         // GIVEN AOD interrupt
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // Configure UdfpsView to accept the ACTION_UP event
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
         } else {
@@ -833,7 +888,7 @@
         moveEvent.recycle();
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // Configure UdfpsView to accept the finger up event
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
         } else {
@@ -844,7 +899,7 @@
         mFgExecutor.advanceClockToNext();
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // THEN the display should be unconfigured once. If the timeout action is not
             // cancelled, the display would be unconfigured twice which would cause two
             // FP attempts.
@@ -856,23 +911,23 @@
 
     @Test
     public void aodInterruptCancelTimeoutActionOnAcquired() {
-        runForAllUdfpsTypes(this::aodInterruptCancelTimeoutActionOnAcquiredForSensor);
+        runWithAllParams(this::aodInterruptCancelTimeoutActionOnAcquiredParameterized);
     }
 
-    private void aodInterruptCancelTimeoutActionOnAcquiredForSensor(
-            FingerprintSensorPropertiesInternal sensorProps) throws RemoteException {
+    private void aodInterruptCancelTimeoutActionOnAcquiredParameterized(TestParams testParams)
+            throws RemoteException {
         reset(mUdfpsView);
         when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
 
         // GIVEN AOD interrupt
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // Configure UdfpsView to accept the acquired event
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
         } else {
@@ -880,7 +935,7 @@
         }
 
         // WHEN acquired is received
-        mOverlayController.onAcquired(sensorProps.sensorId,
+        mOverlayController.onAcquired(testParams.sensorProps.sensorId,
                 BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD);
 
         // Configure UdfpsView to accept the ACTION_DOWN event
@@ -900,7 +955,7 @@
         moveEvent.recycle();
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // Configure UdfpsView to accept the finger up event
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
         } else {
@@ -911,7 +966,7 @@
         mFgExecutor.advanceClockToNext();
         mFgExecutor.runAllReady();
 
-        if (sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
+        if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // THEN the display should be unconfigured once. If the timeout action is not
             // cancelled, the display would be unconfigured twice which would cause two
             // FP attempts.
@@ -923,15 +978,14 @@
 
     @Test
     public void aodInterruptScreenOff() {
-        runForAllUdfpsTypes(this::aodInterruptScreenOffForSensor);
+        runWithAllParams(this::aodInterruptScreenOffParameterized);
     }
 
-    private void aodInterruptScreenOffForSensor(FingerprintSensorPropertiesInternal sensorProps)
-            throws RemoteException {
+    private void aodInterruptScreenOffParameterized(TestParams testParams) throws RemoteException {
         reset(mUdfpsView);
 
         // GIVEN screen off
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOff();
         mFgExecutor.runAllReady();
@@ -945,17 +999,16 @@
 
     @Test
     public void aodInterrupt_fingerprintNotRunning() {
-        runForAllUdfpsTypes(this::aodInterrupt_fingerprintNotRunningForSensor);
+        runWithAllParams(this::aodInterrupt_fingerprintNotRunningParameterized);
     }
 
-    private void aodInterrupt_fingerprintNotRunningForSensor(
-            FingerprintSensorPropertiesInternal sensorProps) throws RemoteException {
+    private void aodInterrupt_fingerprintNotRunningParameterized(TestParams testParams)
+            throws RemoteException {
         reset(mUdfpsView);
 
         // GIVEN showing overlay
-        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD,
-                mUdfpsOverlayControllerCallback);
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
+                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerBaseTest.java
index 75629f4..3c61382 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerBaseTest.java
@@ -94,6 +94,11 @@
             mKeyguardStateControllerCallbackCaptor;
     protected KeyguardStateController.Callback mKeyguardStateControllerCallback;
 
+    private @Captor ArgumentCaptor<StatusBarKeyguardViewManager.KeyguardViewManagerCallback>
+            mKeyguardViewManagerCallbackArgumentCaptor;
+    protected StatusBarKeyguardViewManager.KeyguardViewManagerCallback mKeyguardViewManagerCallback;
+
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -143,15 +148,22 @@
     }
 
     public UdfpsKeyguardViewController createUdfpsKeyguardViewController() {
-        return createUdfpsKeyguardViewController(false);
+        return createUdfpsKeyguardViewController(false, false);
+    }
+
+    public void captureKeyGuardViewManagerCallback() {
+        verify(mStatusBarKeyguardViewManager).addCallback(
+                mKeyguardViewManagerCallbackArgumentCaptor.capture());
+        mKeyguardViewManagerCallback = mKeyguardViewManagerCallbackArgumentCaptor.getValue();
     }
 
     protected UdfpsKeyguardViewController createUdfpsKeyguardViewController(
-            boolean useModernBouncer) {
+            boolean useModernBouncer, boolean useExpandedOverlay) {
         mFeatureFlags.set(Flags.MODERN_BOUNCER, useModernBouncer);
+        mFeatureFlags.set(Flags.UDFPS_NEW_TOUCH_DETECTION, useExpandedOverlay);
         when(mStatusBarKeyguardViewManager.getPrimaryBouncer()).thenReturn(
                 useModernBouncer ? null : mBouncer);
-        return new UdfpsKeyguardViewController(
+        UdfpsKeyguardViewController controller = new UdfpsKeyguardViewController(
                 mView,
                 mStatusBarStateController,
                 mShadeExpansionStateManager,
@@ -168,5 +180,6 @@
                 mActivityLaunchAnimator,
                 mFeatureFlags,
                 mPrimaryBouncerInteractor);
+        return controller;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 16728b6..babe533 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeast;
@@ -30,6 +31,7 @@
 
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
+import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
 
@@ -52,7 +54,8 @@
 
     @Override
     public UdfpsKeyguardViewController createUdfpsKeyguardViewController() {
-        return createUdfpsKeyguardViewController(/* useModernBouncer */ false);
+        return createUdfpsKeyguardViewController(/* useModernBouncer */ false,
+                /* useExpandedOverlay */ false);
     }
 
     @Test
@@ -422,4 +425,37 @@
         verify(mBouncer).addBouncerExpansionCallback(mBouncerExpansionCallbackCaptor.capture());
         mBouncerExpansionCallback = mBouncerExpansionCallbackCaptor.getValue();
     }
+
+    @Test
+    // TODO(b/259264861): Tracking Bug
+    public void testUdfpsExpandedOverlayOn() {
+        // GIVEN view is attached and useExpandedOverlay is true
+        mController = createUdfpsKeyguardViewController(false, true);
+        mController.onViewAttached();
+        captureKeyGuardViewManagerCallback();
+
+        // WHEN a touch is received
+        mKeyguardViewManagerCallback.onTouch(
+                MotionEvent.obtain(0, 0, 0, 0, 0, 0));
+
+        // THEN udfpsController onTouch is not called
+        assertTrue(mView.mUseExpandedOverlay);
+        verify(mUdfpsController, never()).onTouch(any());
+    }
+
+    @Test
+    // TODO(b/259264861): Tracking Bug
+    public void testUdfpsExpandedOverlayOff() {
+        // GIVEN view is attached and useExpandedOverlay is false
+        mController.onViewAttached();
+        captureKeyGuardViewManagerCallback();
+
+        // WHEN a touch is received
+        mKeyguardViewManagerCallback.onTouch(
+                MotionEvent.obtain(0, 0, 0, 0, 0, 0));
+
+        // THEN udfpsController onTouch is called
+        assertFalse(mView.mUseExpandedOverlay);
+        verify(mUdfpsController).onTouch(any());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 68e744e..517e27a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -72,7 +72,10 @@
                 mock(KeyguardBypassController::class.java),
                 mKeyguardUpdateMonitor
             )
-        return createUdfpsKeyguardViewController(/* useModernBouncer */ true)
+        return createUdfpsKeyguardViewController(
+            /* useModernBouncer */ true, /* useExpandedOverlay */
+            false
+        )
     }
 
     /** After migration, replaces LockIconViewControllerTest version */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
index 2af0557..d159714 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.ripple.RippleView
+import com.android.systemui.surfaceeffects.ripple.RippleView
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.ConfigurationController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index f8579ff..0fadc13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -120,6 +120,7 @@
 
         mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
         mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true);
+        mFakeFeatureFlags.set(Flags.MEDIA_FALSING_PENALTY, true);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsEditingActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsEditingActivityTest.kt
index 0b72a68..3b6f7d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsEditingActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsEditingActivityTest.kt
@@ -10,10 +10,12 @@
 import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.intercepting.SingleActivityFactory
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.CustomIconCache
 import com.android.systemui.controls.controller.ControlsControllerImpl
 import com.android.systemui.controls.ui.ControlsUiController
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
 import java.util.concurrent.CountDownLatch
 import org.junit.Before
 import org.junit.Rule
@@ -30,9 +32,11 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
 class ControlsEditingActivityTest : SysuiTestCase() {
+    private val uiExecutor = FakeExecutor(FakeSystemClock())
+
     @Mock lateinit var controller: ControlsControllerImpl
 
-    @Mock lateinit var broadcastDispatcher: BroadcastDispatcher
+    @Mock lateinit var userTracker: UserTracker
 
     @Mock lateinit var customIconCache: CustomIconCache
 
@@ -54,8 +58,9 @@
                 ) {
                 override fun create(intent: Intent?): TestableControlsEditingActivity {
                     return TestableControlsEditingActivity(
+                        uiExecutor,
                         controller,
-                        broadcastDispatcher,
+                        userTracker,
                         customIconCache,
                         uiController,
                         mockDispatcher,
@@ -92,13 +97,14 @@
     }
 
     public class TestableControlsEditingActivity(
+        private val executor: FakeExecutor,
         private val controller: ControlsControllerImpl,
-        private val broadcastDispatcher: BroadcastDispatcher,
+        private val userTracker: UserTracker,
         private val customIconCache: CustomIconCache,
         private val uiController: ControlsUiController,
         private val mockDispatcher: OnBackInvokedDispatcher,
         private val latch: CountDownLatch
-    ) : ControlsEditingActivity(controller, broadcastDispatcher, customIconCache, uiController) {
+    ) : ControlsEditingActivity(executor, controller, userTracker, customIconCache, uiController) {
         override fun getOnBackInvokedDispatcher(): OnBackInvokedDispatcher {
             return mockDispatcher
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsFavoritingActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsFavoritingActivityTest.kt
index 4b0f7e6..0f06de2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsFavoritingActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsFavoritingActivityTest.kt
@@ -9,10 +9,10 @@
 import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.intercepting.SingleActivityFactory
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.controller.ControlsControllerImpl
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.settings.UserTracker
 import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
@@ -37,7 +37,7 @@
 
     @Mock lateinit var listingController: ControlsListingController
 
-    @Mock lateinit var broadcastDispatcher: BroadcastDispatcher
+    @Mock lateinit var userTracker: UserTracker
 
     @Mock lateinit var uiController: ControlsUiController
 
@@ -60,7 +60,7 @@
                         executor,
                         controller,
                         listingController,
-                        broadcastDispatcher,
+                        userTracker,
                         uiController,
                         mockDispatcher,
                         latch
@@ -97,7 +97,7 @@
         executor: Executor,
         controller: ControlsControllerImpl,
         listingController: ControlsListingController,
-        broadcastDispatcher: BroadcastDispatcher,
+        userTracker: UserTracker,
         uiController: ControlsUiController,
         private val mockDispatcher: OnBackInvokedDispatcher,
         private val latch: CountDownLatch
@@ -106,7 +106,7 @@
             executor,
             controller,
             listingController,
-            broadcastDispatcher,
+            userTracker,
             uiController
         ) {
         override fun getOnBackInvokedDispatcher(): OnBackInvokedDispatcher {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
index db41d8d..98ff8d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
@@ -16,27 +16,43 @@
 
 package com.android.systemui.controls.management
 
+import android.Manifest
 import android.content.ComponentName
 import android.content.Context
 import android.content.ContextWrapper
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
 import android.content.pm.ServiceInfo
+import android.os.Bundle
 import android.os.UserHandle
+import android.service.controls.ControlsProviderService
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.settingslib.applications.ServiceListing
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.controls.ControlsServiceInfo
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags.USE_APP_PANELS
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argThat
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import org.junit.After
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatcher
 import org.mockito.Mock
-import org.mockito.Mockito
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.inOrder
 import org.mockito.Mockito.mock
@@ -51,10 +67,8 @@
 class ControlsListingControllerImplTest : SysuiTestCase() {
 
     companion object {
-        private const val TEST_LABEL = "TEST_LABEL"
-        private const val TEST_PERMISSION = "permission"
-        fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
-        fun <T> any(): T = Mockito.any<T>()
+        private const val FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or
+                PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong()
     }
 
     @Mock
@@ -63,15 +77,17 @@
     private lateinit var mockCallback: ControlsListingController.ControlsListingCallback
     @Mock
     private lateinit var mockCallbackOther: ControlsListingController.ControlsListingCallback
-    @Mock
-    private lateinit var serviceInfo: ServiceInfo
-    @Mock
-    private lateinit var serviceInfo2: ServiceInfo
     @Mock(stubOnly = true)
     private lateinit var userTracker: UserTracker
+    @Mock(stubOnly = true)
+    private lateinit var dumpManager: DumpManager
+    @Mock
+    private lateinit var packageManager: PackageManager
+    @Mock
+    private lateinit var featureFlags: FeatureFlags
 
-    private var componentName = ComponentName("pkg1", "class1")
-    private var componentName2 = ComponentName("pkg2", "class2")
+    private var componentName = ComponentName("pkg", "class1")
+    private var activityName = ComponentName("pkg", "activity")
 
     private val executor = FakeExecutor(FakeSystemClock())
 
@@ -87,9 +103,15 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(serviceInfo.componentName).thenReturn(componentName)
-        `when`(serviceInfo2.componentName).thenReturn(componentName2)
         `when`(userTracker.userId).thenReturn(user)
+        `when`(userTracker.userContext).thenReturn(context)
+        // Return disabled by default
+        `when`(packageManager.getComponentEnabledSetting(any()))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED)
+        mContext.setMockPackageManager(packageManager)
+
+        // Return true by default, we'll test the false path
+        `when`(featureFlags.isEnabled(USE_APP_PANELS)).thenReturn(true)
 
         val wrapper = object : ContextWrapper(mContext) {
             override fun createContextAsUser(user: UserHandle, flags: Int): Context {
@@ -97,7 +119,14 @@
             }
         }
 
-        controller = ControlsListingControllerImpl(wrapper, executor, { mockSL }, userTracker)
+        controller = ControlsListingControllerImpl(
+                wrapper,
+                executor,
+                { mockSL },
+                userTracker,
+                dumpManager,
+                featureFlags
+        )
         verify(mockSL).addCallback(capture(serviceListingCallbackCaptor))
     }
 
@@ -123,9 +152,16 @@
             Unit
         }
         `when`(mockServiceListing.reload()).then {
-            callback?.onServicesReloaded(listOf(serviceInfo))
+            callback?.onServicesReloaded(listOf(ServiceInfo(componentName)))
         }
-        ControlsListingControllerImpl(mContext, exec, { mockServiceListing }, userTracker)
+        ControlsListingControllerImpl(
+                mContext,
+                exec,
+                { mockServiceListing },
+                userTracker,
+                dumpManager,
+                featureFlags
+        )
     }
 
     @Test
@@ -148,7 +184,7 @@
 
     @Test
     fun testCallbackGetsList() {
-        val list = listOf(serviceInfo)
+        val list = listOf(ServiceInfo(componentName))
         controller.addCallback(mockCallback)
         controller.addCallback(mockCallbackOther)
 
@@ -188,6 +224,8 @@
 
     @Test
     fun testChangeUserSendsCorrectServiceUpdate() {
+        val serviceInfo = ServiceInfo(componentName)
+
         val list = listOf(serviceInfo)
         controller.addCallback(mockCallback)
 
@@ -223,4 +261,297 @@
         verify(mockCallback).onServicesUpdated(capture(captor))
         assertEquals(0, captor.value.size)
     }
+
+    @Test
+    fun test_nullPanelActivity() {
+        val list = listOf(ServiceInfo(componentName))
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testNoActivity_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityWithoutPermission_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        setUpQueryResult(listOf(ActivityInfo(activityName)))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityPermissionNotExported_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        setUpQueryResult(listOf(
+                ActivityInfo(activityName, permission = Manifest.permission.BIND_CONTROLS)
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityDisabled_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityEnabled_correctPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        `when`(packageManager.getComponentEnabledSetting(eq(activityName)))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertEquals(activityName, controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityDefaultEnabled_correctPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        `when`(packageManager.getComponentEnabledSetting(eq(activityName)))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        enabled = true,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertEquals(activityName, controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityDefaultDisabled_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName
+        )
+
+        `when`(packageManager.getComponentEnabledSetting(eq(activityName)))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        enabled = false,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityDefaultEnabled_flagDisabled_nullPanel() {
+        `when`(featureFlags.isEnabled(USE_APP_PANELS)).thenReturn(false)
+        val serviceInfo = ServiceInfo(
+                componentName,
+                activityName,
+        )
+
+        `when`(packageManager.getComponentEnabledSetting(eq(activityName)))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        enabled = true,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testActivityDifferentPackage_nullPanel() {
+        val serviceInfo = ServiceInfo(
+                componentName,
+                ComponentName("other_package", "cls")
+        )
+
+        `when`(packageManager.getComponentEnabledSetting(eq(activityName)))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+
+        setUpQueryResult(listOf(
+                ActivityInfo(
+                        activityName,
+                        enabled = true,
+                        exported = true,
+                        permission = Manifest.permission.BIND_CONTROLS
+                )
+        ))
+
+        val list = listOf(serviceInfo)
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+
+        assertNull(controller.getCurrentServices()[0].panelActivity)
+    }
+
+    @Test
+    fun testListingsNotModifiedByCallback() {
+        // This test checks that if the list passed to the callback is modified, it has no effect
+        // in the resulting services
+        val list = mutableListOf<ServiceInfo>()
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        list.add(ServiceInfo(ComponentName("a", "b")))
+        executor.runAllReady()
+
+        assertTrue(controller.getCurrentServices().isEmpty())
+    }
+
+    private fun ServiceInfo(
+            componentName: ComponentName,
+            panelActivityComponentName: ComponentName? = null
+    ): ServiceInfo {
+        return ServiceInfo().apply {
+            packageName = componentName.packageName
+            name = componentName.className
+            panelActivityComponentName?.let {
+                metaData = Bundle().apply {
+                    putString(
+                            ControlsProviderService.META_DATA_PANEL_ACTIVITY,
+                            it.flattenToShortString()
+                    )
+                }
+            }
+        }
+    }
+
+    private fun ActivityInfo(
+        componentName: ComponentName,
+        exported: Boolean = false,
+        enabled: Boolean = true,
+        permission: String? = null
+    ): ActivityInfo {
+        return ActivityInfo().apply {
+            packageName = componentName.packageName
+            name = componentName.className
+            this.permission = permission
+            this.exported = exported
+            this.enabled = enabled
+        }
+    }
+
+    private fun setUpQueryResult(infos: List<ActivityInfo>) {
+        `when`(
+                packageManager.queryIntentActivitiesAsUser(
+                        argThat(IntentMatcher(activityName)),
+                        argThat(FlagsMatcher(FLAGS)),
+                        eq(UserHandle.of(user))
+                )
+        ).thenReturn(infos.map {
+            ResolveInfo().apply { activityInfo = it }
+        })
+    }
+
+    private class IntentMatcher(
+            private val componentName: ComponentName
+    ) : ArgumentMatcher<Intent> {
+        override fun matches(argument: Intent?): Boolean {
+            return argument?.component == componentName
+        }
+    }
+
+    private class FlagsMatcher(
+            private val flags: Long
+    ) : ArgumentMatcher<PackageManager.ResolveInfoFlags> {
+        override fun matches(argument: PackageManager.ResolveInfoFlags?): Boolean {
+            return flags == argument?.value
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
index acc6222..56c3efe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
@@ -25,11 +25,11 @@
 import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.intercepting.SingleActivityFactory
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.settings.UserTracker
 import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
@@ -56,7 +56,7 @@
 
     @Mock lateinit var controlsController: ControlsController
 
-    @Mock lateinit var broadcastDispatcher: BroadcastDispatcher
+    @Mock lateinit var userTracker: UserTracker
 
     @Mock lateinit var uiController: ControlsUiController
 
@@ -80,7 +80,7 @@
                         backExecutor,
                         listingController,
                         controlsController,
-                        broadcastDispatcher,
+                        userTracker,
                         uiController,
                         mockDispatcher,
                         latch
@@ -118,7 +118,7 @@
         backExecutor: Executor,
         listingController: ControlsListingController,
         controlsController: ControlsController,
-        broadcastDispatcher: BroadcastDispatcher,
+        userTracker: UserTracker,
         uiController: ControlsUiController,
         private val mockDispatcher: OnBackInvokedDispatcher,
         private val latch: CountDownLatch
@@ -128,7 +128,7 @@
             backExecutor,
             listingController,
             controlsController,
-            broadcastDispatcher,
+            userTracker,
             uiController
         ) {
         override fun getOnBackInvokedDispatcher(): OnBackInvokedDispatcher {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
index efb3db7..314b176 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.controls.controller.ControlInfo
 import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import org.junit.After
@@ -46,9 +47,10 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Captor
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
+import java.util.concurrent.Executor
 
 @MediumTest
 @RunWith(AndroidTestingRunner::class)
@@ -67,6 +69,10 @@
     private lateinit var controller: ControlsController
 
     @Mock
+    private lateinit var mainExecutor: Executor
+    @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
     private lateinit var listingController: ControlsListingController
     @Mock
     private lateinit var iIntentSender: IIntentSender
@@ -81,8 +87,9 @@
             ) {
                     override fun create(intent: Intent?): TestControlsRequestDialog {
                         return TestControlsRequestDialog(
+                                mainExecutor,
                                 controller,
-                                fakeBroadcastDispatcher,
+                                userTracker,
                                 listingController
                         )
                     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
index 3f6308b..ec239f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
@@ -16,11 +16,13 @@
 
 package com.android.systemui.controls.management
 
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.settings.UserTracker
+import java.util.concurrent.Executor
 
 class TestControlsRequestDialog(
+    mainExecutor: Executor,
     controller: ControlsController,
-    dispatcher: BroadcastDispatcher,
+    userTracker: UserTracker,
     listingController: ControlsListingController
-) : ControlsRequestDialog(controller, dispatcher, listingController)
\ No newline at end of file
+) : ControlsRequestDialog(mainExecutor, controller, userTracker, listingController)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index c40c187..20d3cd5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -49,6 +49,7 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.doze.DozeSensors.TriggerSensor;
 import com.android.systemui.plugins.SensorManagerPlugin;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -97,6 +98,8 @@
     @Mock
     private DevicePostureController mDevicePostureController;
     @Mock
+    private UserTracker mUserTracker;
+    @Mock
     private ProximitySensor mProximitySensor;
 
     // Capture listeners so that they can be used to send events
@@ -426,7 +429,7 @@
         DozeSensors dozeSensors = new DozeSensors(mSensorManager, mDozeParameters,
                 mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
                 mProximitySensor, mFakeSettings, mAuthController,
-                mDevicePostureController);
+                mDevicePostureController, mUserTracker);
 
         for (TriggerSensor sensor : dozeSensors.mTriggerSensors) {
             assertFalse(sensor.mIgnoresSetting);
@@ -438,7 +441,7 @@
             super(mSensorManager, mDozeParameters,
                     mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
                     mProximitySensor, mFakeSettings, mAuthController,
-                    mDevicePostureController);
+                    mDevicePostureController, mUserTracker);
             for (TriggerSensor sensor : mTriggerSensors) {
                 if (sensor instanceof PluginSensor
                         && ((PluginSensor) sensor).mPluginSensor.getType()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6091d3a..82432ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -49,6 +49,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent;
 import com.android.systemui.log.SessionTracker;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -98,6 +99,8 @@
     @Mock
     private DevicePostureController mDevicePostureController;
     @Mock
+    private UserTracker mUserTracker;
+    @Mock
     private SessionTracker mSessionTracker;
 
     private DozeTriggers mTriggers;
@@ -131,7 +134,7 @@
                 asyncSensorManager, wakeLock, mDockManager, mProximitySensor,
                 mProximityCheck, mDozeLog, mBroadcastDispatcher, new FakeSettings(),
                 mAuthController, mUiEventLogger, mSessionTracker, mKeyguardStateController,
-                mDevicePostureController);
+                mDevicePostureController, mUserTracker);
         mTriggers.setDozeMachine(mMachine);
         waitForSensorManager();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
new file mode 100644
index 0000000..99406ed
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -0,0 +1,125 @@
+package com.android.systemui.dreams
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dreams.complication.ComplicationHostViewController
+import com.android.systemui.statusbar.BlurUtils
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
+
+    companion object {
+        private const val DREAM_IN_BLUR_ANIMATION_DURATION = 1L
+        private const val DREAM_IN_BLUR_ANIMATION_DELAY = 2L
+        private const val DREAM_IN_COMPLICATIONS_ANIMATION_DURATION = 3L
+        private const val DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY = 4L
+        private const val DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY = 5L
+        private const val DREAM_OUT_TRANSLATION_Y_DISTANCE = 6
+        private const val DREAM_OUT_TRANSLATION_Y_DURATION = 7L
+        private const val DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM = 8L
+        private const val DREAM_OUT_TRANSLATION_Y_DELAY_TOP = 9L
+        private const val DREAM_OUT_ALPHA_DURATION = 10L
+        private const val DREAM_OUT_ALPHA_DELAY_BOTTOM = 11L
+        private const val DREAM_OUT_ALPHA_DELAY_TOP = 12L
+        private const val DREAM_OUT_BLUR_DURATION = 13L
+    }
+
+    @Mock private lateinit var mockAnimator: AnimatorSet
+    @Mock private lateinit var blurUtils: BlurUtils
+    @Mock private lateinit var hostViewController: ComplicationHostViewController
+    @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController
+    @Mock private lateinit var stateController: DreamOverlayStateController
+    private lateinit var controller: DreamOverlayAnimationsController
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        controller =
+            DreamOverlayAnimationsController(
+                blurUtils,
+                hostViewController,
+                statusBarViewController,
+                stateController,
+                DREAM_IN_BLUR_ANIMATION_DURATION,
+                DREAM_IN_BLUR_ANIMATION_DELAY,
+                DREAM_IN_COMPLICATIONS_ANIMATION_DURATION,
+                DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY,
+                DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY,
+                DREAM_OUT_TRANSLATION_Y_DISTANCE,
+                DREAM_OUT_TRANSLATION_Y_DURATION,
+                DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM,
+                DREAM_OUT_TRANSLATION_Y_DELAY_TOP,
+                DREAM_OUT_ALPHA_DURATION,
+                DREAM_OUT_ALPHA_DELAY_BOTTOM,
+                DREAM_OUT_ALPHA_DELAY_TOP,
+                DREAM_OUT_BLUR_DURATION
+            )
+    }
+
+    @Test
+    fun testExitAnimationOnEnd() {
+        val mockCallback: () -> Unit = mock()
+
+        controller.startExitAnimations(
+            view = mock(),
+            doneCallback = mockCallback,
+            animatorBuilder = { mockAnimator }
+        )
+
+        val captor = argumentCaptor<Animator.AnimatorListener>()
+        verify(mockAnimator).addListener(captor.capture())
+        val listener = captor.value
+
+        verify(mockCallback, never()).invoke()
+        listener.onAnimationEnd(mockAnimator)
+        verify(mockCallback, times(1)).invoke()
+    }
+
+    @Test
+    fun testCancellation() {
+        controller.startExitAnimations(
+            view = mock(),
+            doneCallback = mock(),
+            animatorBuilder = { mockAnimator }
+        )
+
+        verify(mockAnimator, never()).cancel()
+        controller.cancelAnimations()
+        verify(mockAnimator, times(1)).cancel()
+    }
+
+    @Test
+    fun testExitAfterStartWillCancel() {
+        val mockStartAnimator: AnimatorSet = mock()
+        val mockExitAnimator: AnimatorSet = mock()
+
+        controller.startEntryAnimations(view = mock(), animatorBuilder = { mockStartAnimator })
+
+        verify(mockStartAnimator, never()).cancel()
+
+        controller.startExitAnimations(
+            view = mock(),
+            doneCallback = mock(),
+            animatorBuilder = { mockExitAnimator }
+        )
+
+        // Verify that we cancelled the start animator in favor of the exit
+        // animator.
+        verify(mockStartAnimator, times(1)).cancel()
+        verify(mockExitAnimator, never()).cancel()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 517804d..73c226d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -204,7 +204,7 @@
         mController.onViewAttached();
 
         verify(mAnimationsController).startEntryAnimations(mDreamOverlayContainerView);
-        verify(mAnimationsController, never()).cancelRunningEntryAnimations();
+        verify(mAnimationsController, never()).cancelAnimations();
     }
 
     @Test
@@ -221,6 +221,6 @@
         mController.onViewAttached();
         mController.onViewDetached();
 
-        verify(mAnimationsController).cancelRunningEntryAnimations();
+        verify(mAnimationsController).cancelAnimations();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index f04a37f..ffb8342 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -337,4 +338,28 @@
         verify(mDreamOverlayComponent).getDreamOverlayContainerViewController();
         verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor();
     }
+
+    @Test
+    public void testWakeUp() throws RemoteException {
+        final IBinder proxy = mService.onBind(new Intent());
+        final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
+
+        // Inform the overlay service of dream starting.
+        overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+                true /*shouldShowComplication*/);
+        mMainExecutor.runAllReady();
+
+        final Runnable callback = mock(Runnable.class);
+        mService.onWakeUp(callback);
+        mMainExecutor.runAllReady();
+        verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
+    }
+
+    @Test
+    public void testWakeUpBeforeStartDoesNothing() {
+        final Runnable callback = mock(Runnable.class);
+        mService.onWakeUp(callback);
+        mMainExecutor.runAllReady();
+        verify(mDreamOverlayContainerViewController, never()).wakeUp(callback, mMainExecutor);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
index 849ac5e..7a2ba95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
@@ -347,21 +347,22 @@
 
         addComplication(engine, thirdViewInfo);
 
-        // The first added view should now be underneath the second view.
+        // The first added view should now be underneath the third view.
         verifyChange(firstViewInfo, false, lp -> {
             assertThat(lp.topToBottom == thirdViewInfo.view.getId()).isTrue();
             assertThat(lp.endToEnd == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
             assertThat(lp.topMargin).isEqualTo(margin);
         });
 
-        // The second view should be in underneath the third view.
+        // The second view should be to the start of the third view.
         verifyChange(secondViewInfo, false, lp -> {
             assertThat(lp.endToStart == thirdViewInfo.view.getId()).isTrue();
             assertThat(lp.topToTop == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
             assertThat(lp.getMarginEnd()).isEqualTo(margin);
         });
 
-        // The third view should be in at the top.
+        // The third view should be at the top end corner. No margin should be applied if not
+        // specified.
         verifyChange(thirdViewInfo, true, lp -> {
             assertThat(lp.topToTop == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
             assertThat(lp.endToEnd == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
@@ -425,14 +426,14 @@
 
         addComplication(engine, thirdViewInfo);
 
-        // The first added view should now be underneath the second view.
+        // The first added view should now be underneath the third view.
         verifyChange(firstViewInfo, false, lp -> {
             assertThat(lp.topToBottom == thirdViewInfo.view.getId()).isTrue();
             assertThat(lp.endToEnd == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
             assertThat(lp.topMargin).isEqualTo(complicationMargin);
         });
 
-        // The second view should be in underneath the third view.
+        // The second view should be to the start of the third view.
         verifyChange(secondViewInfo, false, lp -> {
             assertThat(lp.endToStart == thirdViewInfo.view.getId()).isTrue();
             assertThat(lp.topToTop == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
@@ -441,6 +442,69 @@
     }
 
     /**
+     * Ensures the root complication applies margin if specified.
+     */
+    @Test
+    public void testRootComplicationSpecifiedMargin() {
+        final int defaultMargin = 5;
+        final int complicationMargin = 10;
+        final ComplicationLayoutEngine engine =
+                new ComplicationLayoutEngine(mLayout, defaultMargin, mTouchSession, 0, 0);
+
+        final ViewInfo firstViewInfo = new ViewInfo(
+                new ComplicationLayoutParams(
+                        100,
+                        100,
+                        ComplicationLayoutParams.POSITION_TOP
+                                | ComplicationLayoutParams.POSITION_END,
+                        ComplicationLayoutParams.DIRECTION_DOWN,
+                        0),
+                Complication.CATEGORY_STANDARD,
+                mLayout);
+
+        addComplication(engine, firstViewInfo);
+
+        final ViewInfo secondViewInfo = new ViewInfo(
+                new ComplicationLayoutParams(
+                        100,
+                        100,
+                        ComplicationLayoutParams.POSITION_TOP
+                                | ComplicationLayoutParams.POSITION_END,
+                        ComplicationLayoutParams.DIRECTION_START,
+                        0),
+                Complication.CATEGORY_SYSTEM,
+                mLayout);
+
+        addComplication(engine, secondViewInfo);
+
+        firstViewInfo.clearInvocations();
+        secondViewInfo.clearInvocations();
+
+        final ViewInfo thirdViewInfo = new ViewInfo(
+                new ComplicationLayoutParams(
+                        100,
+                        100,
+                        ComplicationLayoutParams.POSITION_TOP
+                                | ComplicationLayoutParams.POSITION_END,
+                        ComplicationLayoutParams.DIRECTION_START,
+                        1,
+                        complicationMargin),
+                Complication.CATEGORY_SYSTEM,
+                mLayout);
+
+        addComplication(engine, thirdViewInfo);
+
+        // The third view is the root view and has specified margin, which should be applied based
+        // on its direction.
+        verifyChange(thirdViewInfo, true, lp -> {
+            assertThat(lp.getMarginStart()).isEqualTo(0);
+            assertThat(lp.getMarginEnd()).isEqualTo(complicationMargin);
+            assertThat(lp.topMargin).isEqualTo(0);
+            assertThat(lp.bottomMargin).isEqualTo(0);
+        });
+    }
+
+    /**
      * Ensures layout in a particular position updates.
      */
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java
index cb7e47b..ce7561e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java
@@ -97,6 +97,31 @@
     }
 
     /**
+     * Ensures ComplicationLayoutParams correctly returns whether the complication specified margin.
+     */
+    @Test
+    public void testIsMarginSpecified() {
+        final ComplicationLayoutParams paramsNoMargin = new ComplicationLayoutParams(
+                100,
+                100,
+                ComplicationLayoutParams.POSITION_TOP
+                        | ComplicationLayoutParams.POSITION_START,
+                ComplicationLayoutParams.DIRECTION_DOWN,
+                0);
+        assertThat(paramsNoMargin.isMarginSpecified()).isFalse();
+
+        final ComplicationLayoutParams paramsWithMargin = new ComplicationLayoutParams(
+                100,
+                100,
+                ComplicationLayoutParams.POSITION_TOP
+                        | ComplicationLayoutParams.POSITION_START,
+                ComplicationLayoutParams.DIRECTION_DOWN,
+                0,
+                20 /*margin*/);
+        assertThat(paramsWithMargin.isMarginSpecified()).isTrue();
+    }
+
+    /**
      * Ensures unspecified margin uses default.
      */
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
index aa8c93e..30ad485 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
@@ -90,7 +90,10 @@
     private ActivityStarter mActivityStarter;
 
     @Mock
-    UiEventLogger mUiEventLogger;
+    private UiEventLogger mUiEventLogger;
+
+    @Captor
+    private ArgumentCaptor<DreamOverlayStateController.Callback> mStateCallbackCaptor;
 
     @Before
     public void setup() {
@@ -164,6 +167,29 @@
         verify(mDreamOverlayStateController).addComplication(mComplication);
     }
 
+    @Test
+    public void complicationAvailability_checkAvailabilityWhenDreamOverlayBecomesActive() {
+        final DreamHomeControlsComplication.Registrant registrant =
+                new DreamHomeControlsComplication.Registrant(mComplication,
+                        mDreamOverlayStateController, mControlsComponent);
+        registrant.start();
+
+        setServiceAvailable(true);
+        setHaveFavorites(false);
+
+        // Complication not available on start.
+        verify(mDreamOverlayStateController, never()).addComplication(mComplication);
+
+        // Favorite controls added, complication should be available now.
+        setHaveFavorites(true);
+
+        // Dream overlay becomes active.
+        setDreamOverlayActive(true);
+
+        // Verify complication is added.
+        verify(mDreamOverlayStateController).addComplication(mComplication);
+    }
+
     /**
      * Ensures clicking home controls chip logs UiEvent.
      */
@@ -196,10 +222,17 @@
 
     private void setServiceAvailable(boolean value) {
         final List<ControlsServiceInfo> serviceInfos = mock(List.class);
+        when(mControlsListingController.getCurrentServices()).thenReturn(serviceInfos);
         when(serviceInfos.isEmpty()).thenReturn(!value);
         triggerControlsListingCallback(serviceInfos);
     }
 
+    private void setDreamOverlayActive(boolean value) {
+        when(mDreamOverlayStateController.isOverlayActive()).thenReturn(value);
+        verify(mDreamOverlayStateController).addCallback(mStateCallbackCaptor.capture());
+        mStateCallbackCaptor.getValue().onStateChanged();
+    }
+
     private void triggerControlsListingCallback(List<ControlsServiceInfo> serviceInfos) {
         verify(mControlsListingController).addCallback(mCallbackCaptor.capture());
         mCallbackCaptor.getValue().onServicesUpdated(serviceInfos);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
index 14a5702..4e3aca7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.dreams.touch;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
@@ -33,6 +31,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.complication.Complication;
 import com.android.systemui.shared.system.InputChannelCompat;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -52,6 +51,7 @@
 @RunWith(AndroidTestingRunner.class)
 public class HideComplicationTouchHandlerTest extends SysuiTestCase {
     private static final int RESTORE_TIMEOUT = 1000;
+    private static final int HIDE_DELAY = 500;
 
     @Mock
     Complication.VisibilityController mVisibilityController;
@@ -71,11 +71,18 @@
     @Mock
     DreamTouchHandler.TouchSession mSession;
 
-    FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
+    @Mock
+    DreamOverlayStateController mStateController;
+
+    FakeSystemClock mClock;
+
+    FakeExecutor mFakeExecutor;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        mClock = new FakeSystemClock();
+        mFakeExecutor = new FakeExecutor(mClock);
     }
 
     /**
@@ -86,10 +93,11 @@
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
                 RESTORE_TIMEOUT,
+                HIDE_DELAY,
                 mTouchInsetManager,
                 mStatusBarKeyguardViewManager,
                 mFakeExecutor,
-                mHandler);
+                mStateController);
 
         // Report multiple active sessions.
         when(mSession.getActiveSessionCount()).thenReturn(2);
@@ -103,8 +111,10 @@
         // Verify session end.
         verify(mSession).pop();
 
+        mClock.advanceTime(HIDE_DELAY);
+
         // Verify no interaction with visibility controller.
-        verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+        verify(mVisibilityController, never()).setVisibility(anyInt());
     }
 
     /**
@@ -115,10 +125,11 @@
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
                 RESTORE_TIMEOUT,
+                HIDE_DELAY,
                 mTouchInsetManager,
                 mStatusBarKeyguardViewManager,
                 mFakeExecutor,
-                mHandler);
+                mStateController);
 
         // Report one session.
         when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -132,8 +143,10 @@
         // Verify session end.
         verify(mSession).pop();
 
+        mClock.advanceTime(HIDE_DELAY);
+
         // Verify no interaction with visibility controller.
-        verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+        verify(mVisibilityController, never()).setVisibility(anyInt());
     }
 
     /**
@@ -144,10 +157,11 @@
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
                 RESTORE_TIMEOUT,
+                HIDE_DELAY,
                 mTouchInsetManager,
                 mStatusBarKeyguardViewManager,
                 mFakeExecutor,
-                mHandler);
+                mStateController);
 
         // Report one session
         when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -177,8 +191,10 @@
         // Verify session ended.
         verify(mSession).pop();
 
+        mClock.advanceTime(HIDE_DELAY);
+
         // Verify no interaction with visibility controller.
-        verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+        verify(mVisibilityController, never()).setVisibility(anyInt());
     }
 
     /**
@@ -189,10 +205,11 @@
         final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
                 mVisibilityController,
                 RESTORE_TIMEOUT,
+                HIDE_DELAY,
                 mTouchInsetManager,
                 mStatusBarKeyguardViewManager,
                 mFakeExecutor,
-                mHandler);
+                mStateController);
 
         // Report one session
         when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -221,11 +238,11 @@
         inputEventListenerCaptor.getValue().onInputEvent(mMotionEvent);
         mFakeExecutor.runAllReady();
 
-        // Verify callback to restore visibility cancelled.
-        verify(mHandler).removeCallbacks(any());
-
+        // Verify visibility controller doesn't hide until after timeout
+        verify(mVisibilityController, never()).setVisibility(eq(View.INVISIBLE));
+        mClock.advanceTime(HIDE_DELAY);
         // Verify visibility controller told to hide complications.
-        verify(mVisibilityController).setVisibility(eq(View.INVISIBLE), anyBoolean());
+        verify(mVisibilityController).setVisibility(eq(View.INVISIBLE));
 
         Mockito.clearInvocations(mVisibilityController, mHandler);
 
@@ -235,11 +252,8 @@
         mFakeExecutor.runAllReady();
 
         // Verify visibility controller told to show complications.
-        ArgumentCaptor<Runnable> delayRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
-        verify(mHandler).postDelayed(delayRunnableCaptor.capture(),
-                eq(Long.valueOf(RESTORE_TIMEOUT)));
-        delayRunnableCaptor.getValue().run();
-        verify(mVisibilityController).setVisibility(eq(View.VISIBLE), anyBoolean());
+        mClock.advanceTime(RESTORE_TIMEOUT);
+        verify(mVisibilityController).setVisibility(eq(View.VISIBLE));
 
         // Verify session ended.
         verify(mSession).pop();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt
new file mode 100644
index 0000000..1e7b1f2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.flags
+
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class FeatureFlagsDebugRestarterTest : SysuiTestCase() {
+    private lateinit var restarter: FeatureFlagsDebugRestarter
+
+    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock private lateinit var systemExitRestarter: SystemExitRestarter
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        restarter = FeatureFlagsDebugRestarter(wakefulnessLifecycle, systemExitRestarter)
+    }
+
+    @Test
+    fun testRestart_ImmediateWhenAsleep() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        restarter.restart()
+        verify(systemExitRestarter).restart()
+    }
+
+    @Test
+    fun testRestart_WaitsForSceenOff() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+
+        restarter.restart()
+        verify(systemExitRestarter, never()).restart()
+
+        val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
+        verify(wakefulnessLifecycle).addObserver(captor.capture())
+
+        captor.value.onFinishedGoingToSleep()
+
+        verify(systemExitRestarter).restart()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
new file mode 100644
index 0000000..68ca48d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.flags
+
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class FeatureFlagsReleaseRestarterTest : SysuiTestCase() {
+    private lateinit var restarter: FeatureFlagsReleaseRestarter
+
+    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock private lateinit var batteryController: BatteryController
+    @Mock private lateinit var systemExitRestarter: SystemExitRestarter
+    private val executor = FakeExecutor(FakeSystemClock())
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        restarter =
+            FeatureFlagsReleaseRestarter(
+                wakefulnessLifecycle,
+                batteryController,
+                executor,
+                systemExitRestarter
+            )
+    }
+
+    @Test
+    fun testRestart_ScheduledWhenReady() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+        assertThat(executor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun testRestart_RestartsWhenIdle() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        restarter.restart()
+        verify(systemExitRestarter, never()).restart()
+        executor.advanceClockToLast()
+        executor.runAllReady()
+        verify(systemExitRestarter).restart()
+    }
+
+    @Test
+    fun testRestart_NotScheduledWhenAwake() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+        assertThat(executor.numPending()).isEqualTo(0)
+    }
+
+    @Test
+    fun testRestart_NotScheduledWhenNotPluggedIn() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        whenever(batteryController.isPluggedIn).thenReturn(false)
+
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+        assertThat(executor.numPending()).isEqualTo(0)
+    }
+
+    @Test
+    fun testRestart_NotDoubleSheduled() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+        restarter.restart()
+        assertThat(executor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun testWakefulnessLifecycle_CanRestart() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+
+        val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
+        verify(wakefulnessLifecycle).addObserver(captor.capture())
+
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+
+        captor.value.onFinishedGoingToSleep()
+        assertThat(executor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun testBatteryController_CanRestart() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+        whenever(batteryController.isPluggedIn).thenReturn(false)
+        assertThat(executor.numPending()).isEqualTo(0)
+        restarter.restart()
+
+        val captor =
+            ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
+        verify(batteryController).addCallback(captor.capture())
+
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        captor.value.onBatteryLevelChanged(0, true, true)
+        assertThat(executor.numPending()).isEqualTo(1)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 8b1554c..d52616b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -63,6 +63,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions;
 import com.android.systemui.settings.UserContextProvider;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -103,6 +104,7 @@
     @Mock private SecureSettings mSecureSettings;
     @Mock private Resources mResources;
     @Mock private ConfigurationController mConfigurationController;
+    @Mock private UserTracker mUserTracker;
     @Mock private KeyguardStateController mKeyguardStateController;
     @Mock private UserManager mUserManager;
     @Mock private TrustManager mTrustManager;
@@ -152,6 +154,7 @@
                 mVibratorHelper,
                 mResources,
                 mConfigurationController,
+                mUserTracker,
                 mKeyguardStateController,
                 mUserManager,
                 mTrustManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt
new file mode 100644
index 0000000..8395f02
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard
+
+import android.content.ContentValues
+import android.content.pm.PackageManager
+import android.content.pm.ProviderInfo
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SystemUIAppComponentFactoryBase
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
+
+    @Mock private lateinit var lockPatternUtils: LockPatternUtils
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var activityStarter: ActivityStarter
+
+    private lateinit var underTest: KeyguardQuickAffordanceProvider
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        underTest = KeyguardQuickAffordanceProvider()
+        val scope = CoroutineScope(IMMEDIATE)
+        val selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock<UserFileManager>().apply {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = userTracker,
+            )
+        val quickAffordanceRepository =
+            KeyguardQuickAffordanceRepository(
+                appContext = context,
+                scope = scope,
+                selectionManager = selectionManager,
+                configs =
+                    setOf(
+                        FakeKeyguardQuickAffordanceConfig(
+                            key = AFFORDANCE_1,
+                            pickerIconResourceId = 1,
+                        ),
+                        FakeKeyguardQuickAffordanceConfig(
+                            key = AFFORDANCE_2,
+                            pickerIconResourceId = 2,
+                        ),
+                    ),
+                legacySettingSyncer =
+                    KeyguardQuickAffordanceLegacySettingSyncer(
+                        scope = scope,
+                        backgroundDispatcher = IMMEDIATE,
+                        secureSettings = FakeSettings(),
+                        selectionsManager = selectionManager,
+                    ),
+            )
+        underTest.interactor =
+            KeyguardQuickAffordanceInteractor(
+                keyguardInteractor =
+                    KeyguardInteractor(
+                        repository = FakeKeyguardRepository(),
+                    ),
+                registry = mock(),
+                lockPatternUtils = lockPatternUtils,
+                keyguardStateController = keyguardStateController,
+                userTracker = userTracker,
+                activityStarter = activityStarter,
+                featureFlags =
+                    FakeFeatureFlags().apply {
+                        set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
+                    },
+                repository = { quickAffordanceRepository },
+            )
+
+        underTest.attachInfoForTesting(
+            context,
+            ProviderInfo().apply { authority = Contract.AUTHORITY },
+        )
+        context.contentResolver.addProvider(Contract.AUTHORITY, underTest)
+        context.testablePermissions.setPermission(
+            Contract.PERMISSION,
+            PackageManager.PERMISSION_GRANTED,
+        )
+    }
+
+    @Test
+    fun `onAttachInfo - reportsContext`() {
+        val callback: SystemUIAppComponentFactoryBase.ContextAvailableCallback = mock()
+        underTest.setContextAvailableCallback(callback)
+
+        underTest.attachInfo(context, null)
+
+        verify(callback).onContextAvailable(context)
+    }
+
+    @Test
+    fun getType() {
+        assertThat(underTest.getType(Contract.AffordanceTable.URI))
+            .isEqualTo(
+                "vnd.android.cursor.dir/vnd." +
+                    "${Contract.AUTHORITY}.${Contract.AffordanceTable.TABLE_NAME}"
+            )
+        assertThat(underTest.getType(Contract.SlotTable.URI))
+            .isEqualTo(
+                "vnd.android.cursor.dir/vnd.${Contract.AUTHORITY}.${Contract.SlotTable.TABLE_NAME}"
+            )
+        assertThat(underTest.getType(Contract.SelectionTable.URI))
+            .isEqualTo(
+                "vnd.android.cursor.dir/vnd." +
+                    "${Contract.AUTHORITY}.${Contract.SelectionTable.TABLE_NAME}"
+            )
+    }
+
+    @Test
+    fun `insert and query selection`() =
+        runBlocking(IMMEDIATE) {
+            val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+            val affordanceId = AFFORDANCE_2
+
+            insertSelection(
+                slotId = slotId,
+                affordanceId = affordanceId,
+            )
+
+            assertThat(querySelections())
+                .isEqualTo(
+                    listOf(
+                        Selection(
+                            slotId = slotId,
+                            affordanceId = affordanceId,
+                        )
+                    )
+                )
+        }
+
+    @Test
+    fun `query slots`() =
+        runBlocking(IMMEDIATE) {
+            assertThat(querySlots())
+                .isEqualTo(
+                    listOf(
+                        Slot(
+                            id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                            capacity = 1,
+                        ),
+                        Slot(
+                            id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                            capacity = 1,
+                        ),
+                    )
+                )
+        }
+
+    @Test
+    fun `query affordances`() =
+        runBlocking(IMMEDIATE) {
+            assertThat(queryAffordances())
+                .isEqualTo(
+                    listOf(
+                        Affordance(
+                            id = AFFORDANCE_1,
+                            name = AFFORDANCE_1,
+                            iconResourceId = 1,
+                        ),
+                        Affordance(
+                            id = AFFORDANCE_2,
+                            name = AFFORDANCE_2,
+                            iconResourceId = 2,
+                        ),
+                    )
+                )
+        }
+
+    @Test
+    fun `delete and query selection`() =
+        runBlocking(IMMEDIATE) {
+            insertSelection(
+                slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                affordanceId = AFFORDANCE_1,
+            )
+            insertSelection(
+                slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                affordanceId = AFFORDANCE_2,
+            )
+
+            context.contentResolver.delete(
+                Contract.SelectionTable.URI,
+                "${Contract.SelectionTable.Columns.SLOT_ID} = ? AND" +
+                    " ${Contract.SelectionTable.Columns.AFFORDANCE_ID} = ?",
+                arrayOf(
+                    KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                    AFFORDANCE_2,
+                ),
+            )
+
+            assertThat(querySelections())
+                .isEqualTo(
+                    listOf(
+                        Selection(
+                            slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                            affordanceId = AFFORDANCE_1,
+                        )
+                    )
+                )
+        }
+
+    @Test
+    fun `delete all selections in a slot`() =
+        runBlocking(IMMEDIATE) {
+            insertSelection(
+                slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                affordanceId = AFFORDANCE_1,
+            )
+            insertSelection(
+                slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                affordanceId = AFFORDANCE_2,
+            )
+
+            context.contentResolver.delete(
+                Contract.SelectionTable.URI,
+                Contract.SelectionTable.Columns.SLOT_ID,
+                arrayOf(
+                    KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                ),
+            )
+
+            assertThat(querySelections())
+                .isEqualTo(
+                    listOf(
+                        Selection(
+                            slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                            affordanceId = AFFORDANCE_1,
+                        )
+                    )
+                )
+        }
+
+    private fun insertSelection(
+        slotId: String,
+        affordanceId: String,
+    ) {
+        context.contentResolver.insert(
+            Contract.SelectionTable.URI,
+            ContentValues().apply {
+                put(Contract.SelectionTable.Columns.SLOT_ID, slotId)
+                put(Contract.SelectionTable.Columns.AFFORDANCE_ID, affordanceId)
+            }
+        )
+    }
+
+    private fun querySelections(): List<Selection> {
+        return context.contentResolver
+            .query(
+                Contract.SelectionTable.URI,
+                null,
+                null,
+                null,
+                null,
+            )
+            ?.use { cursor ->
+                buildList {
+                    val slotIdColumnIndex =
+                        cursor.getColumnIndex(Contract.SelectionTable.Columns.SLOT_ID)
+                    val affordanceIdColumnIndex =
+                        cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_ID)
+                    if (slotIdColumnIndex == -1 || affordanceIdColumnIndex == -1) {
+                        return@buildList
+                    }
+
+                    while (cursor.moveToNext()) {
+                        add(
+                            Selection(
+                                slotId = cursor.getString(slotIdColumnIndex),
+                                affordanceId = cursor.getString(affordanceIdColumnIndex),
+                            )
+                        )
+                    }
+                }
+            }
+            ?: emptyList()
+    }
+
+    private fun querySlots(): List<Slot> {
+        return context.contentResolver
+            .query(
+                Contract.SlotTable.URI,
+                null,
+                null,
+                null,
+                null,
+            )
+            ?.use { cursor ->
+                buildList {
+                    val idColumnIndex = cursor.getColumnIndex(Contract.SlotTable.Columns.ID)
+                    val capacityColumnIndex =
+                        cursor.getColumnIndex(Contract.SlotTable.Columns.CAPACITY)
+                    if (idColumnIndex == -1 || capacityColumnIndex == -1) {
+                        return@buildList
+                    }
+
+                    while (cursor.moveToNext()) {
+                        add(
+                            Slot(
+                                id = cursor.getString(idColumnIndex),
+                                capacity = cursor.getInt(capacityColumnIndex),
+                            )
+                        )
+                    }
+                }
+            }
+            ?: emptyList()
+    }
+
+    private fun queryAffordances(): List<Affordance> {
+        return context.contentResolver
+            .query(
+                Contract.AffordanceTable.URI,
+                null,
+                null,
+                null,
+                null,
+            )
+            ?.use { cursor ->
+                buildList {
+                    val idColumnIndex = cursor.getColumnIndex(Contract.AffordanceTable.Columns.ID)
+                    val nameColumnIndex =
+                        cursor.getColumnIndex(Contract.AffordanceTable.Columns.NAME)
+                    val iconColumnIndex =
+                        cursor.getColumnIndex(Contract.AffordanceTable.Columns.ICON)
+                    if (idColumnIndex == -1 || nameColumnIndex == -1 || iconColumnIndex == -1) {
+                        return@buildList
+                    }
+
+                    while (cursor.moveToNext()) {
+                        add(
+                            Affordance(
+                                id = cursor.getString(idColumnIndex),
+                                name = cursor.getString(nameColumnIndex),
+                                iconResourceId = cursor.getInt(iconColumnIndex),
+                            )
+                        )
+                    }
+                }
+            }
+            ?: emptyList()
+    }
+
+    data class Slot(
+        val id: String,
+        val capacity: Int,
+    )
+
+    data class Affordance(
+        val id: String,
+        val name: String,
+        val iconResourceId: Int,
+    )
+
+    data class Selection(
+        val slotId: String,
+        val affordanceId: String,
+    )
+
+    companion object {
+        private val IMMEDIATE = Dispatchers.Main.immediate
+        private const val AFFORDANCE_1 = "affordance_1"
+        private const val AFFORDANCE_2 = "affordance_2"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 23516c9..729a1cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.SystemUIInitializerImpl;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -93,6 +94,8 @@
     private NextAlarmController mNextAlarmController;
     @Mock
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private UserTracker mUserTracker;
     private TestableKeyguardSliceProvider mProvider;
     private boolean mIsZenMode;
 
@@ -105,6 +108,7 @@
         mProvider.attachInfo(getContext(), null);
         reset(mContentResolver);
         SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
+        when(mUserTracker.getUserId()).thenReturn(100);
     }
 
     @After
@@ -267,6 +271,7 @@
             mKeyguardBypassController = KeyguardSliceProviderTest.this.mKeyguardBypassController;
             mMediaManager = KeyguardSliceProviderTest.this.mNotificationMediaManager;
             mKeyguardUpdateMonitor = KeyguardSliceProviderTest.this.mKeyguardUpdateMonitor;
+            mUserTracker = KeyguardSliceProviderTest.this.mUserTracker;
         }
 
         @Override
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 b6780a1..45aaaa2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -57,6 +57,7 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -86,6 +87,7 @@
 public class KeyguardViewMediatorTest extends SysuiTestCase {
     private KeyguardViewMediator mViewMediator;
 
+    private @Mock UserTracker mUserTracker;
     private @Mock DevicePolicyManager mDevicePolicyManager;
     private @Mock LockPatternUtils mLockPatternUtils;
     private @Mock KeyguardUpdateMonitor mUpdateMonitor;
@@ -286,6 +288,7 @@
     private void createAndStartViewMediator() {
         mViewMediator = new KeyguardViewMediator(
                 mContext,
+                mUserTracker,
                 mFalsingCollector,
                 mLockPatternUtils,
                 mBroadcastDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
new file mode 100644
index 0000000..623becf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2022 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.app.StatusBarManager
+import android.content.Context
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.camera.CameraGestureHelper
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class CameraQuickAffordanceConfigTest : SysuiTestCase() {
+
+    @Mock private lateinit var cameraGestureHelper: CameraGestureHelper
+    @Mock private lateinit var context: Context
+    private lateinit var underTest: CameraQuickAffordanceConfig
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        underTest = CameraQuickAffordanceConfig(
+                context,
+                cameraGestureHelper,
+        )
+    }
+
+    @Test
+    fun `affordance triggered -- camera launch called`() {
+        //when
+        val result = underTest.onTriggered(null)
+
+        //then
+        verify(cameraGestureHelper)
+                .launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
+        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
new file mode 100644
index 0000000..8ef921e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Context
+import android.content.res.Resources
+import android.provider.Settings
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
+
+    @Mock private lateinit var sharedPrefs: FakeSharedPreferences
+
+    private lateinit var underTest: KeyguardQuickAffordanceLegacySettingSyncer
+
+    private lateinit var testScope: TestScope
+    private lateinit var testDispatcher: TestDispatcher
+    private lateinit var selectionManager: KeyguardQuickAffordanceSelectionManager
+    private lateinit var settings: FakeSettings
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        val context: Context = mock()
+        sharedPrefs = FakeSharedPreferences()
+        whenever(context.getSharedPreferences(anyString(), any())).thenReturn(sharedPrefs)
+        val resources: Resources = mock()
+        whenever(resources.getStringArray(R.array.config_keyguardQuickAffordanceDefaults))
+            .thenReturn(emptyArray())
+        whenever(context.resources).thenReturn(resources)
+
+        testDispatcher = UnconfinedTestDispatcher()
+        testScope = TestScope(testDispatcher)
+        selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = FakeUserTracker(),
+            )
+        settings = FakeSettings()
+        settings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0)
+        settings.putInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET, 0)
+        settings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER, 0)
+
+        underTest =
+            KeyguardQuickAffordanceLegacySettingSyncer(
+                scope = testScope,
+                backgroundDispatcher = testDispatcher,
+                secureSettings = settings,
+                selectionsManager = selectionManager,
+            )
+    }
+
+    @Test
+    fun `Setting a setting selects the affordance`() =
+        testScope.runTest {
+            val job = underTest.startSyncing()
+
+            settings.putInt(
+                Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
+                1,
+            )
+
+            assertThat(
+                    selectionManager
+                        .getSelections()
+                        .getOrDefault(
+                            KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                            emptyList()
+                        )
+                )
+                .contains(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
+
+            job.cancel()
+        }
+
+    @Test
+    fun `Clearing a setting selects the affordance`() =
+        testScope.runTest {
+            val job = underTest.startSyncing()
+
+            settings.putInt(
+                Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
+                1,
+            )
+            settings.putInt(
+                Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
+                0,
+            )
+
+            assertThat(
+                    selectionManager
+                        .getSelections()
+                        .getOrDefault(
+                            KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                            emptyList()
+                        )
+                )
+                .doesNotContain(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
+
+            job.cancel()
+        }
+
+    @Test
+    fun `Selecting an affordance sets its setting`() =
+        testScope.runTest {
+            val job = underTest.startSyncing()
+
+            selectionManager.setSelections(
+                KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                listOf(BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET)
+            )
+
+            advanceUntilIdle()
+            assertThat(settings.getInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET)).isEqualTo(1)
+
+            job.cancel()
+        }
+
+    @Test
+    fun `Unselecting an affordance clears its setting`() =
+        testScope.runTest {
+            val job = underTest.startSyncing()
+
+            selectionManager.setSelections(
+                KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                listOf(BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET)
+            )
+            selectionManager.setSelections(
+                KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+                emptyList()
+            )
+
+            assertThat(settings.getInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET)).isEqualTo(0)
+
+            job.cancel()
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManagerTest.kt
index d2422ad..d8ee9f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceSelectionManagerTest.kt
@@ -17,111 +17,312 @@
 
 package com.android.systemui.keyguard.data.quickaffordance
 
+import android.content.SharedPreferences
+import android.content.pm.UserInfo
 import androidx.test.filters.SmallTest
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(JUnit4::class)
 class KeyguardQuickAffordanceSelectionManagerTest : SysuiTestCase() {
 
+    @Mock private lateinit var userFileManager: UserFileManager
+
     private lateinit var underTest: KeyguardQuickAffordanceSelectionManager
 
+    private lateinit var userTracker: FakeUserTracker
+    private lateinit var sharedPrefs: MutableMap<Int, SharedPreferences>
+
     @Before
     fun setUp() {
-        underTest = KeyguardQuickAffordanceSelectionManager()
+        MockitoAnnotations.initMocks(this)
+        sharedPrefs = mutableMapOf()
+        whenever(userFileManager.getSharedPreferences(anyString(), anyInt(), anyInt())).thenAnswer {
+            val userId = it.arguments[2] as Int
+            sharedPrefs.getOrPut(userId) { FakeSharedPreferences() }
+        }
+        userTracker = FakeUserTracker()
+
+        underTest =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager = userFileManager,
+                userTracker = userTracker,
+            )
     }
 
     @Test
-    fun setSelections() =
-        runBlocking(IMMEDIATE) {
-            var affordanceIdsBySlotId: Map<String, List<String>>? = null
-            val job = underTest.selections.onEach { affordanceIdsBySlotId = it }.launchIn(this)
-            val slotId1 = "slot1"
-            val slotId2 = "slot2"
-            val affordanceId1 = "affordance1"
-            val affordanceId2 = "affordance2"
-            val affordanceId3 = "affordance3"
+    fun setSelections() = runTest {
+        overrideResource(R.array.config_keyguardQuickAffordanceDefaults, arrayOf<String>())
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
+        val slotId1 = "slot1"
+        val slotId2 = "slot2"
+        val affordanceId1 = "affordance1"
+        val affordanceId2 = "affordance2"
+        val affordanceId3 = "affordance3"
 
-            underTest.setSelections(
-                slotId = slotId1,
-                affordanceIds = listOf(affordanceId1),
+        underTest.setSelections(
+            slotId = slotId1,
+            affordanceIds = listOf(affordanceId1),
+        )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId1),
+            ),
+        )
+
+        underTest.setSelections(
+            slotId = slotId2,
+            affordanceIds = listOf(affordanceId2),
+        )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId1),
+                slotId2 to listOf(affordanceId2),
             )
-            assertSelections(
-                affordanceIdsBySlotId,
+        )
+
+        underTest.setSelections(
+            slotId = slotId1,
+            affordanceIds = listOf(affordanceId1, affordanceId3),
+        )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId1, affordanceId3),
+                slotId2 to listOf(affordanceId2),
+            )
+        )
+
+        underTest.setSelections(
+            slotId = slotId1,
+            affordanceIds = listOf(affordanceId3),
+        )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId3),
+                slotId2 to listOf(affordanceId2),
+            )
+        )
+
+        underTest.setSelections(
+            slotId = slotId2,
+            affordanceIds = listOf(),
+        )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId3),
+                slotId2 to listOf(),
+            )
+        )
+
+        job.cancel()
+    }
+
+    @Test
+    fun `remembers selections by user`() = runTest {
+        val slot1 = "slot_1"
+        val slot2 = "slot_2"
+        val affordance1 = "affordance_1"
+        val affordance2 = "affordance_2"
+        val affordance3 = "affordance_3"
+
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
+
+        val userInfos =
+            listOf(
+                UserInfo(/* id= */ 0, "zero", /* flags= */ 0),
+                UserInfo(/* id= */ 1, "one", /* flags= */ 0),
+            )
+        userTracker.set(
+            userInfos = userInfos,
+            selectedUserIndex = 0,
+        )
+        underTest.setSelections(
+            slotId = slot1,
+            affordanceIds = listOf(affordance1),
+        )
+        underTest.setSelections(
+            slotId = slot2,
+            affordanceIds = listOf(affordance2),
+        )
+
+        // Switch to user 1
+        userTracker.set(
+            userInfos = userInfos,
+            selectedUserIndex = 1,
+        )
+        // We never set selections on user 1, so it should be empty.
+        assertSelections(
+            observed = affordanceIdsBySlotId.last(),
+            expected = emptyMap(),
+        )
+        // Now, let's set selections on user 1.
+        underTest.setSelections(
+            slotId = slot1,
+            affordanceIds = listOf(affordance2),
+        )
+        underTest.setSelections(
+            slotId = slot2,
+            affordanceIds = listOf(affordance3),
+        )
+        assertSelections(
+            observed = affordanceIdsBySlotId.last(),
+            expected =
                 mapOf(
-                    slotId1 to listOf(affordanceId1),
+                    slot1 to listOf(affordance2),
+                    slot2 to listOf(affordance3),
                 ),
-            )
+        )
 
-            underTest.setSelections(
-                slotId = slotId2,
-                affordanceIds = listOf(affordanceId2),
-            )
-            assertSelections(
-                affordanceIdsBySlotId,
+        // Switch back to user 0.
+        userTracker.set(
+            userInfos = userInfos,
+            selectedUserIndex = 0,
+        )
+        // Assert that we still remember the old selections for user 0.
+        assertSelections(
+            observed = affordanceIdsBySlotId.last(),
+            expected =
                 mapOf(
-                    slotId1 to listOf(affordanceId1),
-                    slotId2 to listOf(affordanceId2),
-                )
-            )
+                    slot1 to listOf(affordance1),
+                    slot2 to listOf(affordance2),
+                ),
+        )
 
-            underTest.setSelections(
-                slotId = slotId1,
-                affordanceIds = listOf(affordanceId1, affordanceId3),
-            )
-            assertSelections(
-                affordanceIdsBySlotId,
-                mapOf(
-                    slotId1 to listOf(affordanceId1, affordanceId3),
-                    slotId2 to listOf(affordanceId2),
-                )
-            )
+        job.cancel()
+    }
 
-            underTest.setSelections(
-                slotId = slotId1,
-                affordanceIds = listOf(affordanceId3),
-            )
-            assertSelections(
-                affordanceIdsBySlotId,
-                mapOf(
-                    slotId1 to listOf(affordanceId3),
-                    slotId2 to listOf(affordanceId2),
-                )
-            )
+    @Test
+    fun `selections respects defaults`() = runTest {
+        val slotId1 = "slot1"
+        val slotId2 = "slot2"
+        val affordanceId1 = "affordance1"
+        val affordanceId2 = "affordance2"
+        val affordanceId3 = "affordance3"
+        overrideResource(
+            R.array.config_keyguardQuickAffordanceDefaults,
+            arrayOf(
+                "$slotId1:${listOf(affordanceId1, affordanceId3).joinToString(",")}",
+                "$slotId2:${listOf(affordanceId2).joinToString(",")}",
+            ),
+        )
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
 
-            underTest.setSelections(
-                slotId = slotId2,
-                affordanceIds = listOf(),
-            )
-            assertSelections(
-                affordanceIdsBySlotId,
-                mapOf(
-                    slotId1 to listOf(affordanceId3),
-                    slotId2 to listOf(),
-                )
-            )
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId1, affordanceId3),
+                slotId2 to listOf(affordanceId2),
+            ),
+        )
 
-            job.cancel()
-        }
+        job.cancel()
+    }
 
-    private suspend fun assertSelections(
+    @Test
+    fun `selections ignores defaults after selecting an affordance`() = runTest {
+        val slotId1 = "slot1"
+        val slotId2 = "slot2"
+        val affordanceId1 = "affordance1"
+        val affordanceId2 = "affordance2"
+        val affordanceId3 = "affordance3"
+        overrideResource(
+            R.array.config_keyguardQuickAffordanceDefaults,
+            arrayOf(
+                "$slotId1:${listOf(affordanceId1, affordanceId3).joinToString(",")}",
+                "$slotId2:${listOf(affordanceId2).joinToString(",")}",
+            ),
+        )
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
+
+        underTest.setSelections(slotId1, listOf(affordanceId2))
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(affordanceId2),
+                slotId2 to listOf(affordanceId2),
+            ),
+        )
+
+        job.cancel()
+    }
+
+    @Test
+    fun `selections ignores defaults after clearing a slot`() = runTest {
+        val slotId1 = "slot1"
+        val slotId2 = "slot2"
+        val affordanceId1 = "affordance1"
+        val affordanceId2 = "affordance2"
+        val affordanceId3 = "affordance3"
+        overrideResource(
+            R.array.config_keyguardQuickAffordanceDefaults,
+            arrayOf(
+                "$slotId1:${listOf(affordanceId1, affordanceId3).joinToString(",")}",
+                "$slotId2:${listOf(affordanceId2).joinToString(",")}",
+            ),
+        )
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
+
+        underTest.setSelections(slotId1, listOf())
+        assertSelections(
+            affordanceIdsBySlotId.last(),
+            mapOf(
+                slotId1 to listOf(),
+                slotId2 to listOf(affordanceId2),
+            ),
+        )
+
+        job.cancel()
+    }
+
+    private fun assertSelections(
         observed: Map<String, List<String>>?,
         expected: Map<String, List<String>>,
     ) {
         assertThat(underTest.getSelections()).isEqualTo(expected)
         assertThat(observed).isEqualTo(expected)
     }
-
-    companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index 5a7f2bb..d8a3605 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -18,13 +18,20 @@
 package com.android.systemui.keyguard.data.repository
 
 import androidx.test.filters.SmallTest
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
-import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -36,6 +43,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
@@ -51,11 +60,36 @@
     fun setUp() {
         config1 = FakeKeyguardQuickAffordanceConfig("built_in:1")
         config2 = FakeKeyguardQuickAffordanceConfig("built_in:2")
+        val scope = CoroutineScope(IMMEDIATE)
+        val selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock<UserFileManager>().apply {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = FakeUserTracker(),
+            )
+
         underTest =
             KeyguardQuickAffordanceRepository(
-                scope = CoroutineScope(IMMEDIATE),
-                backgroundDispatcher = IMMEDIATE,
-                selectionManager = KeyguardQuickAffordanceSelectionManager(),
+                appContext = context,
+                scope = scope,
+                selectionManager = selectionManager,
+                legacySettingSyncer =
+                    KeyguardQuickAffordanceLegacySettingSyncer(
+                        scope = scope,
+                        backgroundDispatcher = IMMEDIATE,
+                        secureSettings = FakeSettings(),
+                        selectionsManager = selectionManager,
+                    ),
                 configs = setOf(config1, config2),
             )
     }
@@ -119,16 +153,32 @@
 
     @Test
     fun getSlotPickerRepresentations() {
+        val slot1 = "slot1"
+        val slot2 = "slot2"
+        val slot3 = "slot3"
+        context.orCreateTestableResources.addOverride(
+            R.array.config_keyguardQuickAffordanceSlots,
+            arrayOf(
+                "$slot1:2",
+                "$slot2:4",
+                "$slot3:5",
+            ),
+        )
+
         assertThat(underTest.getSlotPickerRepresentations())
             .isEqualTo(
                 listOf(
                     KeyguardSlotPickerRepresentation(
-                        id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
-                        maxSelectedAffordances = 1,
+                        id = slot1,
+                        maxSelectedAffordances = 2,
                     ),
                     KeyguardSlotPickerRepresentation(
-                        id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
-                        maxSelectedAffordances = 1,
+                        id = slot2,
+                        maxSelectedAffordances = 4,
+                    ),
+                    KeyguardSlotPickerRepresentation(
+                        id = slot3,
+                        maxSelectedAffordances = 5,
                     ),
                 )
             )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index ade83cf..6ba0634 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.Position
 import com.android.systemui.doze.DozeHost
@@ -60,12 +61,12 @@
 
         underTest =
             KeyguardRepositoryImpl(
-                    statusBarStateController,
-                    dozeHost,
-                    wakefulnessLifecycle,
-                    biometricUnlockController,
-                    keyguardStateController,
-                    keyguardUpdateMonitor,
+                statusBarStateController,
+                dozeHost,
+                wakefulnessLifecycle,
+                biometricUnlockController,
+                keyguardStateController,
+                keyguardUpdateMonitor,
             )
     }
 
@@ -257,6 +258,48 @@
     }
 
     @Test
+    fun isKeyguardGoingAway() = runBlockingTest {
+        whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
+        var latest: Boolean? = null
+        val job = underTest.isKeyguardGoingAway.onEach { latest = it }.launchIn(this)
+
+        assertThat(latest).isFalse()
+
+        val captor = argumentCaptor<KeyguardStateController.Callback>()
+        verify(keyguardStateController).addCallback(captor.capture())
+
+        whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(true)
+        captor.value.onKeyguardGoingAwayChanged()
+        assertThat(latest).isTrue()
+
+        whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
+        captor.value.onKeyguardGoingAwayChanged()
+        assertThat(latest).isFalse()
+
+        job.cancel()
+    }
+
+    @Test
+    fun isDreaming() = runBlockingTest {
+        whenever(keyguardUpdateMonitor.isDreaming()).thenReturn(false)
+        var latest: Boolean? = null
+        val job = underTest.isDreaming.onEach { latest = it }.launchIn(this)
+
+        assertThat(latest).isFalse()
+
+        val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+
+        captor.value.onDreamingStateChanged(true)
+        assertThat(latest).isTrue()
+
+        captor.value.onDreamingStateChanged(false)
+        assertThat(latest).isFalse()
+
+        job.cancel()
+    }
+
+    @Test
     fun biometricUnlockState() = runBlockingTest {
         val values = mutableListOf<BiometricUnlockModel>()
         val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index 27d5d0a..2b03722 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -25,8 +25,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
+import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
-import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionInfo
 import com.android.systemui.keyguard.shared.model.TransitionState
@@ -38,7 +38,6 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.launchIn
@@ -91,18 +90,51 @@
                 }
             }
 
-            assertSteps(steps, listWithStep(BigDecimal(.1)))
+            assertSteps(steps, listWithStep(BigDecimal(.1)), AOD, LOCKSCREEN)
 
             job.cancel()
             provider.stop()
         }
 
     @Test
-    fun `startTransition called during another transition fails`() {
-        underTest.startTransition(TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, null))
-        underTest.startTransition(TransitionInfo(OWNER_NAME, LOCKSCREEN, BOUNCER, null))
+    fun `starting second transition will cancel the first transition`() {
+        runBlocking(IMMEDIATE) {
+            val (animator, provider) = setupAnimator(this)
 
-        assertThat(wtfHandler.failed).isTrue()
+            val steps = mutableListOf<TransitionStep>()
+            val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
+
+            underTest.startTransition(TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, animator))
+            // 3 yields(), alternating with the animator, results in a value 0.1, which can be
+            // canceled and tested against
+            yield()
+            yield()
+            yield()
+
+            // Now start 2nd transition, which will interrupt the first
+            val job2 = underTest.transition(LOCKSCREEN, AOD).onEach { steps.add(it) }.launchIn(this)
+            val (animator2, provider2) = setupAnimator(this)
+            underTest.startTransition(TransitionInfo(OWNER_NAME, LOCKSCREEN, AOD, animator2))
+
+            val startTime = System.currentTimeMillis()
+            while (animator2.isRunning()) {
+                yield()
+                if (System.currentTimeMillis() - startTime > MAX_TEST_DURATION) {
+                    fail("Failed test due to excessive runtime of: $MAX_TEST_DURATION")
+                }
+            }
+
+            val firstTransitionSteps = listWithStep(step = BigDecimal(.1), stop = BigDecimal(.1))
+            assertSteps(steps.subList(0, 4), firstTransitionSteps, AOD, LOCKSCREEN)
+
+            val secondTransitionSteps = listWithStep(step = BigDecimal(.1), start = BigDecimal(.9))
+            assertSteps(steps.subList(4, steps.size), secondTransitionSteps, LOCKSCREEN, AOD)
+
+            job.cancel()
+            job2.cancel()
+            provider.stop()
+            provider2.stop()
+        }
     }
 
     @Test
@@ -165,11 +197,15 @@
         assertThat(wtfHandler.failed).isTrue()
     }
 
-    private fun listWithStep(step: BigDecimal): List<BigDecimal> {
+    private fun listWithStep(
+        step: BigDecimal,
+        start: BigDecimal = BigDecimal.ZERO,
+        stop: BigDecimal = BigDecimal.ONE,
+    ): List<BigDecimal> {
         val steps = mutableListOf<BigDecimal>()
 
-        var i = BigDecimal.ZERO
-        while (i.compareTo(BigDecimal.ONE) <= 0) {
+        var i = start
+        while (i.compareTo(stop) <= 0) {
             steps.add(i)
             i = (i + step).setScale(2, RoundingMode.HALF_UP)
         }
@@ -177,23 +213,43 @@
         return steps
     }
 
-    private fun assertSteps(steps: List<TransitionStep>, fractions: List<BigDecimal>) {
+    private fun assertSteps(
+        steps: List<TransitionStep>,
+        fractions: List<BigDecimal>,
+        from: KeyguardState,
+        to: KeyguardState,
+    ) {
         assertThat(steps[0])
-            .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
+            .isEqualTo(
+                TransitionStep(
+                    from,
+                    to,
+                    fractions[0].toFloat(),
+                    TransitionState.STARTED,
+                    OWNER_NAME
+                )
+            )
         fractions.forEachIndexed { index, fraction ->
             assertThat(steps[index + 1])
                 .isEqualTo(
                     TransitionStep(
-                        AOD,
-                        LOCKSCREEN,
+                        from,
+                        to,
                         fraction.toFloat(),
                         TransitionState.RUNNING,
                         OWNER_NAME
                     )
                 )
         }
+        val lastValue = fractions[fractions.size - 1].toFloat()
+        val status =
+            if (lastValue < 1f) {
+                TransitionState.CANCELED
+            } else {
+                TransitionState.FINISHED
+            }
         assertThat(steps[steps.size - 1])
-            .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME))
+            .isEqualTo(TransitionStep(from, to, lastValue, status, OWNER_NAME))
 
         assertThat(wtfHandler.failed).isFalse()
     }
@@ -230,7 +286,7 @@
                 scope.launch {
                     frames.collect {
                         // Delay is required for AnimationHandler to properly register a callback
-                        delay(1)
+                        yield()
                         val (frameNumber, callback) = it
                         callback?.doFrame(frameNumber)
                     }
@@ -243,7 +299,7 @@
         }
 
         override fun postFrameCallback(cb: FrameCallback) {
-            frames.value = Pair(++frameCount, cb)
+            frames.value = Pair(frameCount++, cb)
         }
         override fun postCommitCallback(runnable: Runnable) {}
         override fun getFrameTime() = frameCount
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 8b6603d..1e1d3f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -30,17 +30,22 @@
 import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.test.runBlockingTest
@@ -50,6 +55,8 @@
 import org.junit.runners.Parameterized
 import org.junit.runners.Parameterized.Parameter
 import org.junit.runners.Parameterized.Parameters
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.ArgumentMatchers.same
 import org.mockito.Mock
@@ -201,7 +208,6 @@
 
     @Mock private lateinit var lockPatternUtils: LockPatternUtils
     @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var activityStarter: ActivityStarter
     @Mock private lateinit var animationController: ActivityLaunchAnimator.Controller
     @Mock private lateinit var expandable: Expandable
@@ -214,12 +220,14 @@
     @JvmField @Parameter(3) var needsToUnlockFirst: Boolean = false
     @JvmField @Parameter(4) var startActivity: Boolean = false
     private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig
+    private lateinit var userTracker: UserTracker
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         whenever(expandable.activityLaunchController()).thenReturn(animationController)
 
+        userTracker = FakeUserTracker()
         homeControls =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
         val quickAccessWallet =
@@ -228,11 +236,35 @@
             )
         val qrCodeScanner =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
+        val scope = CoroutineScope(IMMEDIATE)
+        val selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock<UserFileManager>().apply {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = userTracker,
+            )
         val quickAffordanceRepository =
             KeyguardQuickAffordanceRepository(
-                scope = CoroutineScope(IMMEDIATE),
-                backgroundDispatcher = IMMEDIATE,
-                selectionManager = KeyguardQuickAffordanceSelectionManager(),
+                appContext = context,
+                scope = scope,
+                selectionManager = selectionManager,
+                legacySettingSyncer =
+                    KeyguardQuickAffordanceLegacySettingSyncer(
+                        scope = scope,
+                        backgroundDispatcher = IMMEDIATE,
+                        secureSettings = FakeSettings(),
+                        selectionsManager = selectionManager,
+                    ),
                 configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
             )
         underTest =
@@ -318,7 +350,6 @@
         needStrongAuthAfterBoot: Boolean = true,
         keyguardIsUnlocked: Boolean = false,
     ) {
-        whenever(userTracker.userHandle).thenReturn(mock())
         whenever(lockPatternUtils.getStrongAuthForUser(any()))
             .thenReturn(
                 if (needStrongAuthAfterBoot) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 3364535..c47e6f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -35,11 +36,14 @@
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -53,6 +57,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.MockitoAnnotations
 
@@ -89,12 +95,36 @@
             )
         qrCodeScanner =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
+        val scope = CoroutineScope(IMMEDIATE)
 
+        val selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock<UserFileManager>().apply {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = userTracker,
+            )
         val quickAffordanceRepository =
             KeyguardQuickAffordanceRepository(
-                scope = CoroutineScope(IMMEDIATE),
-                backgroundDispatcher = IMMEDIATE,
-                selectionManager = KeyguardQuickAffordanceSelectionManager(),
+                appContext = context,
+                scope = scope,
+                selectionManager = selectionManager,
+                legacySettingSyncer =
+                    KeyguardQuickAffordanceLegacySettingSyncer(
+                        scope = scope,
+                        backgroundDispatcher = IMMEDIATE,
+                        secureSettings = FakeSettings(),
+                        selectionsManager = selectionManager,
+                    ),
                 configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
             )
         featureFlags =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index c85f7b9..3269f5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -93,7 +93,6 @@
     @Test
     fun testShow_isScrimmed() {
         mPrimaryBouncerInteractor.show(true)
-        verify(repository).setShowMessage(null)
         verify(repository).setOnScreenTurnedOff(false)
         verify(repository).setKeyguardAuthenticated(null)
         verify(repository).setPrimaryHide(false)
@@ -155,6 +154,7 @@
         mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN)
         verify(repository).setPrimaryVisible(false)
         verify(repository).setPrimaryShow(null)
+        verify(repository).setPrimaryHide(true)
         verify(falsingCollector).onBouncerHidden()
         verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
         verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 78148c4..ecc63ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -38,10 +39,13 @@
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.max
 import kotlin.math.min
@@ -56,6 +60,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.verifyZeroInteractions
@@ -115,11 +120,35 @@
         whenever(userTracker.userHandle).thenReturn(mock())
         whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
             .thenReturn(LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED)
+        val scope = CoroutineScope(IMMEDIATE)
+        val selectionManager =
+            KeyguardQuickAffordanceSelectionManager(
+                context = context,
+                userFileManager =
+                    mock<UserFileManager>().apply {
+                        whenever(
+                                getSharedPreferences(
+                                    anyString(),
+                                    anyInt(),
+                                    anyInt(),
+                                )
+                            )
+                            .thenReturn(FakeSharedPreferences())
+                    },
+                userTracker = userTracker,
+            )
         val quickAffordanceRepository =
             KeyguardQuickAffordanceRepository(
-                scope = CoroutineScope(IMMEDIATE),
-                backgroundDispatcher = IMMEDIATE,
-                selectionManager = KeyguardQuickAffordanceSelectionManager(),
+                appContext = context,
+                scope = scope,
+                selectionManager = selectionManager,
+                legacySettingSyncer =
+                    KeyguardQuickAffordanceLegacySettingSyncer(
+                        scope = scope,
+                        backgroundDispatcher = IMMEDIATE,
+                        secureSettings = FakeSettings(),
+                        selectionsManager = selectionManager,
+                    ),
                 configs =
                     setOf(
                         homeControlsQuickAffordanceConfig,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarViewModelTest.kt
index 7cd8e74..56c91bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/player/SeekBarViewModelTest.kt
@@ -42,6 +42,7 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Mock
 import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
@@ -464,7 +465,7 @@
     fun onFalseTapOrTouch() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
         whenever(falsingManager.isFalseTouch(Classifier.MEDIA_SEEKBAR)).thenReturn(true)
-        whenever(falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)).thenReturn(true)
+        whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true)
         viewModel.updateController(mockController)
         val pos = 169
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
index 575b1c6..9d33e6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
@@ -22,13 +22,13 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.broadcast.BroadcastSender
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.ui.MediaPlayerData
 import com.android.systemui.media.controls.util.MediaUiEventLogger
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
@@ -64,7 +64,7 @@
 class MediaDataFilterTest : SysuiTestCase() {
 
     @Mock private lateinit var listener: MediaDataManager.Listener
-    @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+    @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var broadcastSender: BroadcastSender
     @Mock private lateinit var mediaDataManager: MediaDataManager
     @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager
@@ -85,7 +85,7 @@
         mediaDataFilter =
             MediaDataFilter(
                 context,
-                broadcastDispatcher,
+                userTracker,
                 broadcastSender,
                 lockscreenUserManager,
                 executor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index 11eb26b..8bd7163 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -20,6 +20,8 @@
 import android.app.Notification.MediaStyle
 import android.app.PendingIntent
 import android.app.smartspace.SmartspaceAction
+import android.app.smartspace.SmartspaceConfig
+import android.app.smartspace.SmartspaceManager
 import android.app.smartspace.SmartspaceTarget
 import android.content.Intent
 import android.graphics.Bitmap
@@ -106,6 +108,7 @@
     lateinit var metadataBuilder: MediaMetadata.Builder
     lateinit var backgroundExecutor: FakeExecutor
     lateinit var foregroundExecutor: FakeExecutor
+    lateinit var uiExecutor: FakeExecutor
     @Mock lateinit var dumpManager: DumpManager
     @Mock lateinit var broadcastDispatcher: BroadcastDispatcher
     @Mock lateinit var mediaTimeoutListener: MediaTimeoutListener
@@ -117,6 +120,7 @@
     @Mock lateinit var listener: MediaDataManager.Listener
     @Mock lateinit var pendingIntent: PendingIntent
     @Mock lateinit var activityStarter: ActivityStarter
+    @Mock lateinit var smartspaceManager: SmartspaceManager
     lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider
     @Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget
     @Mock private lateinit var mediaRecommendationItem: SmartspaceAction
@@ -131,6 +135,7 @@
     @Mock private lateinit var tunerService: TunerService
     @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable>
     @Captor lateinit var callbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit>
+    @Captor lateinit var smartSpaceConfigBuilderCaptor: ArgumentCaptor<SmartspaceConfig>
 
     private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
 
@@ -145,6 +150,7 @@
     fun setup() {
         foregroundExecutor = FakeExecutor(clock)
         backgroundExecutor = FakeExecutor(clock)
+        uiExecutor = FakeExecutor(clock)
         smartspaceMediaDataProvider = SmartspaceMediaDataProvider()
         Settings.Secure.putInt(
             context.contentResolver,
@@ -155,6 +161,7 @@
             MediaDataManager(
                 context = context,
                 backgroundExecutor = backgroundExecutor,
+                uiExecutor = uiExecutor,
                 foregroundExecutor = foregroundExecutor,
                 mediaControllerFactory = mediaControllerFactory,
                 broadcastDispatcher = broadcastDispatcher,
@@ -172,7 +179,8 @@
                 systemClock = clock,
                 tunerService = tunerService,
                 mediaFlags = mediaFlags,
-                logger = logger
+                logger = logger,
+                smartspaceManager = smartspaceManager,
             )
         verify(tunerService)
             .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION))
@@ -191,6 +199,7 @@
                 putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
                 putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
             }
+        verify(smartspaceManager).createSmartspaceSession(capture(smartSpaceConfigBuilderCaptor))
         whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller)
         whenever(controller.transportControls).thenReturn(transportControls)
         whenever(controller.playbackInfo).thenReturn(playbackInfo)
@@ -767,15 +776,14 @@
             .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
     }
 
-    @Ignore("b/233283726")
     @Test
     fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
         smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
         verify(logger).getNewInstanceId()
 
         smartspaceMediaDataProvider.onTargetsAvailable(listOf())
-        foregroundExecutor.advanceClockToLast()
-        foregroundExecutor.runAllReady()
+        uiExecutor.advanceClockToLast()
+        uiExecutor.runAllReady()
 
         verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
         verifyNoMoreInteractions(logger)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/ColorSchemeTransitionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/ColorSchemeTransitionTest.kt
index a8f4138..a943746 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/ColorSchemeTransitionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/ColorSchemeTransitionTest.kt
@@ -25,7 +25,8 @@
 import com.android.systemui.media.controls.models.GutsViewHolder
 import com.android.systemui.media.controls.models.player.MediaViewHolder
 import com.android.systemui.monet.ColorScheme
-import com.android.systemui.ripple.MultiRippleController
+import com.android.systemui.surfaceeffects.ripple.MultiRippleController
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController
 import junit.framework.Assert.assertEquals
 import org.junit.After
 import org.junit.Before
@@ -62,6 +63,7 @@
     @Mock private lateinit var mediaViewHolder: MediaViewHolder
     @Mock private lateinit var gutsViewHolder: GutsViewHolder
     @Mock private lateinit var multiRippleController: MultiRippleController
+    @Mock private lateinit var turbulenceNoiseController: TurbulenceNoiseController
 
     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
 
@@ -76,6 +78,7 @@
                 context,
                 mediaViewHolder,
                 multiRippleController,
+                turbulenceNoiseController,
                 animatingColorTransitionFactory
             )
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index 1ad2ca9b..761773b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -78,9 +78,10 @@
 import com.android.systemui.media.dialog.MediaOutputDialogFactory
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.ripple.MultiRippleView
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.surfaceeffects.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
 import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.KotlinArgumentCaptor
@@ -178,6 +179,7 @@
     private lateinit var dismiss: FrameLayout
     private lateinit var dismissText: TextView
     private lateinit var multiRippleView: MultiRippleView
+    private lateinit var turbulenceNoiseView: TurbulenceNoiseView
 
     private lateinit var session: MediaSession
     private lateinit var device: MediaDeviceData
@@ -210,7 +212,10 @@
     private lateinit var recSubtitle3: TextView
     private var shouldShowBroadcastButton: Boolean = false
     private val fakeFeatureFlag =
-        FakeFeatureFlags().apply { this.set(Flags.UMO_SURFACE_RIPPLE, false) }
+        FakeFeatureFlags().apply {
+            this.set(Flags.UMO_SURFACE_RIPPLE, false)
+            this.set(Flags.MEDIA_FALSING_PENALTY, true)
+        }
 
     @JvmField @Rule val mockito = MockitoJUnit.rule()
 
@@ -382,6 +387,7 @@
             }
 
         multiRippleView = MultiRippleView(context, null)
+        turbulenceNoiseView = TurbulenceNoiseView(context, null)
 
         whenever(viewHolder.player).thenReturn(view)
         whenever(viewHolder.appIcon).thenReturn(appIcon)
@@ -425,6 +431,7 @@
         whenever(viewHolder.actionsTopBarrier).thenReturn(actionsTopBarrier)
 
         whenever(viewHolder.multiRippleView).thenReturn(multiRippleView)
+        whenever(viewHolder.turbulenceNoiseView).thenReturn(turbulenceNoiseView)
     }
 
     /** Initialize elements for the recommendation view holder */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
index 68a5f47..885cc54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
@@ -261,7 +261,12 @@
     @Test
     fun updateView_noOverrides_usesInfoFromAppIcon() {
         controllerReceiver.displayView(
-            ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appNameOverride = null)
+            ChipReceiverInfo(
+                routeInfo,
+                appIconDrawableOverride = null,
+                appNameOverride = null,
+                id = "id",
+            )
         )
 
         val view = getChipView()
@@ -274,7 +279,12 @@
         val drawableOverride = context.getDrawable(R.drawable.ic_celebration)!!
 
         controllerReceiver.displayView(
-            ChipReceiverInfo(routeInfo, drawableOverride, appNameOverride = null)
+            ChipReceiverInfo(
+                routeInfo,
+                drawableOverride,
+                appNameOverride = null,
+                id = "id",
+            )
         )
 
         val view = getChipView()
@@ -286,7 +296,12 @@
         val appNameOverride = "Sweet New App"
 
         controllerReceiver.displayView(
-            ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appNameOverride)
+            ChipReceiverInfo(
+                routeInfo,
+                appIconDrawableOverride = null,
+                appNameOverride,
+                id = "id",
+            )
         )
 
         val view = getChipView()
@@ -340,7 +355,7 @@
             .addFeature("feature")
             .setClientPackageName(packageName)
             .build()
-        return ChipReceiverInfo(routeInfo, null, null)
+        return ChipReceiverInfo(routeInfo, null, null, id = "id")
     }
 
     private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
index 939af16..d35a212 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt
@@ -4,6 +4,7 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -11,11 +12,11 @@
 import com.android.wm.shell.util.GroupedRecentTaskInfo
 import com.google.common.truth.Truth.assertThat
 import java.util.*
+import java.util.function.Consumer
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
-import java.util.function.Consumer
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
@@ -23,8 +24,14 @@
 
     private val dispatcher = Dispatchers.Unconfined
     private val recentTasks: RecentTasks = mock()
+    private val userTracker: UserTracker = mock()
     private val recentTaskListProvider =
-        ShellRecentTaskListProvider(dispatcher, Runnable::run, Optional.of(recentTasks))
+        ShellRecentTaskListProvider(
+            dispatcher,
+            Runnable::run,
+            Optional.of(recentTasks),
+            userTracker
+        )
 
     @Test
     fun loadRecentTasks_oneTask_returnsTheSameTask() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index cd7a949..72e022e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -439,6 +439,17 @@
         verify(mQSPanelController).setExpanded(false);
     }
 
+    @Test
+    public void startsListeningAfterStateChangeToExpanded_inSplitShade() {
+        QSFragment fragment = resumeAndGetFragment();
+        enableSplitShade();
+        fragment.setQsVisible(true);
+        clearInvocations(mQSPanelController);
+
+        fragment.setExpanded(true);
+        verify(mQSPanelController).setListening(true, true);
+    }
+
     @Override
     protected Fragment instantiate(Context context, String className, Bundle arguments) {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 5abc0e1..35c8cc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -27,6 +27,8 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.content.Context;
+import android.content.res.Resources;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -42,16 +44,22 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TileLayoutTest extends SysuiTestCase {
-    private TileLayout mTileLayout;
+    private Resources mResources;
     private int mLayoutSizeForOneTile;
+    private TileLayout mTileLayout; // under test
 
     @Before
     public void setUp() throws Exception {
-        mTileLayout = new TileLayout(mContext);
+        Context context = Mockito.spy(mContext);
+        mResources = Mockito.spy(context.getResources());
+        Mockito.when(mContext.getResources()).thenReturn(mResources);
+
+        mTileLayout = new TileLayout(context);
         // Layout needs to leave space for the tile margins. Three times the margin size is
         // sufficient for any number of columns.
         mLayoutSizeForOneTile =
@@ -203,4 +211,21 @@
         verify(tileRecord1.tileView).setPosition(0);
         verify(tileRecord2.tileView).setPosition(1);
     }
+
+    @Test
+    public void resourcesChanged_updateResources_returnsTrue() {
+        Mockito.when(mResources.getInteger(R.integer.quick_settings_num_columns)).thenReturn(1);
+        mTileLayout.updateResources(); // setup with 1
+        Mockito.when(mResources.getInteger(R.integer.quick_settings_num_columns)).thenReturn(2);
+
+        assertEquals(true, mTileLayout.updateResources());
+    }
+
+    @Test
+    public void resourcesSame_updateResources_returnsFalse() {
+        Mockito.when(mResources.getInteger(R.integer.quick_settings_num_columns)).thenReturn(1);
+        mTileLayout.updateResources(); // setup with 1
+
+        assertEquals(false, mTileLayout.updateResources());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 73a0cbc..030c59f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.qs.QSHost
 import com.android.systemui.qs.logging.QSLogger
 import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.settings.GlobalSettings
 import com.google.common.truth.Truth.assertThat
 import dagger.Lazy
@@ -64,6 +65,8 @@
     private lateinit var mConnectivityManager: Lazy<ConnectivityManager>
     @Mock
     private lateinit var mGlobalSettings: GlobalSettings
+    @Mock
+    private lateinit var mUserTracker: UserTracker
     private lateinit var mTestableLooper: TestableLooper
     private lateinit var mTile: AirplaneModeTile
 
@@ -87,7 +90,8 @@
             mQsLogger,
             mBroadcastDispatcher,
             mConnectivityManager,
-            mGlobalSettings)
+            mGlobalSettings,
+            mUserTracker)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
index 3131f60..08a90b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -42,27 +42,21 @@
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
 class UserDetailViewAdapterTest : SysuiTestCase() {
 
-    @Mock
-    private lateinit var mUserSwitcherController: UserSwitcherController
-    @Mock
-    private lateinit var mParent: ViewGroup
-    @Mock
-    private lateinit var mUserDetailItemView: UserDetailItemView
-    @Mock
-    private lateinit var mOtherView: View
-    @Mock
-    private lateinit var mInflatedUserDetailItemView: UserDetailItemView
-    @Mock
-    private lateinit var mLayoutInflater: LayoutInflater
+    @Mock private lateinit var mUserSwitcherController: UserSwitcherController
+    @Mock private lateinit var mParent: ViewGroup
+    @Mock private lateinit var mUserDetailItemView: UserDetailItemView
+    @Mock private lateinit var mOtherView: View
+    @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView
+    @Mock private lateinit var mLayoutInflater: LayoutInflater
     private var falsingManagerFake: FalsingManagerFake = FalsingManagerFake()
     private lateinit var adapter: UserDetailView.Adapter
     private lateinit var uiEventLogger: UiEventLoggerFake
@@ -77,10 +71,13 @@
         `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
             .thenReturn(mInflatedUserDetailItemView)
         `when`(mParent.context).thenReturn(mContext)
-        adapter = UserDetailView.Adapter(
-            mContext, mUserSwitcherController, uiEventLogger,
-            falsingManagerFake
-        )
+        adapter =
+            UserDetailView.Adapter(
+                mContext,
+                mUserSwitcherController,
+                uiEventLogger,
+                falsingManagerFake
+            )
         mPicture = UserIcons.convertToBitmap(mContext.getDrawable(R.drawable.ic_avatar_user))
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 7b1e5c9..8d1ccd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -5,6 +5,7 @@
 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.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_HORIZONTAL_WEIGHT;
 import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_VERTICAL_WEIGHT;
 import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX;
@@ -13,6 +14,7 @@
 
 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;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -36,6 +38,7 @@
 import android.os.Handler;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
@@ -55,6 +58,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -68,12 +73,15 @@
 import com.android.wifitrackerlib.MergedCarrierEntry;
 import com.android.wifitrackerlib.WifiEntry;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -84,6 +92,9 @@
 public class InternetDialogControllerTest extends SysuiTestCase {
 
     private static final int SUB_ID = 1;
+    private static final int SUB_ID2 = 2;
+
+    private MockitoSession mStaticMockSession;
 
     //SystemUIToast
     private static final int GRAVITY_FLAGS = Gravity.FILL_HORIZONTAL | Gravity.FILL_VERTICAL;
@@ -151,6 +162,8 @@
     @Mock
     private SignalStrength mSignalStrength;
 
+    private FakeFeatureFlags mFlags = new FakeFeatureFlags();
+
     private TestableResources mTestableResources;
     private InternetDialogController mInternetDialogController;
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -159,6 +172,10 @@
 
     @Before
     public void setUp() {
+        mStaticMockSession = mockitoSession()
+                .mockStatic(SubscriptionManager.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
         MockitoAnnotations.initMocks(this);
         mTestableResources = mContext.getOrCreateTestableResources();
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
@@ -175,6 +192,7 @@
         mAccessPoints.add(mWifiEntry1);
         when(mAccessPointController.getMergedCarrierEntry()).thenReturn(mMergedCarrierEntry);
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{SUB_ID});
+        when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(SUB_ID);
         when(mToastFactory.createToast(any(), anyString(), anyString(), anyInt(), anyInt()))
             .thenReturn(mSystemUIToast);
         when(mSystemUIToast.getView()).thenReturn(mToastView);
@@ -188,13 +206,19 @@
                 mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
                 mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
                 mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
-                mLocationController, mDialogLaunchAnimator, mWifiStateWorker);
+                mLocationController, mDialogLaunchAnimator, mWifiStateWorker, mFlags);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
                 mInternetDialogController.mOnSubscriptionsChangedListener);
         mInternetDialogController.onStart(mInternetDialogCallback, true);
         mInternetDialogController.onAccessPointsChanged(mAccessPoints);
         mInternetDialogController.mActivityStarter = mActivityStarter;
         mInternetDialogController.mWifiIconInjector = mWifiIconInjector;
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, false);
+    }
+
+    @After
+    public void tearDown() {
+        mStaticMockSession.finishMocking();
     }
 
     @Test
@@ -325,15 +349,45 @@
 
     @Test
     public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        InternetDialogController spyController = spy(mInternetDialogController);
         fakeAirplaneModeEnabled(false);
         when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
-        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
+        spyController.onAccessPointsChanged(null /* accessPoints */);
+
+        doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId();
+        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
+        doReturn(mServiceState).when(mTelephonyManager).getServiceState();
+        doReturn(TelephonyManager.DATA_DISCONNECTED).when(mTelephonyManager).getDataState();
+
+        assertFalse(TextUtils.equals(spyController.getSubtitleText(false),
+                getResourcesString("all_network_unavailable")));
+
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(spyController).getActiveAutoSwitchNonDdsSubId();
+        spyController.onAccessPointsChanged(null /* accessPoints */);
+        assertTrue(TextUtils.equals(spyController.getSubtitleText(false),
+                getResourcesString("all_network_unavailable")));
+    }
+
+    @Test
+    public void getSubtitleText_withNoService_returnNoNetworksAvailable_flagOff() {
+        InternetDialogController spyController = spy(mInternetDialogController);
+        fakeAirplaneModeEnabled(false);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
+        spyController.onAccessPointsChanged(null /* accessPoints */);
 
         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
         doReturn(mServiceState).when(mTelephonyManager).getServiceState();
         doReturn(TelephonyManager.DATA_DISCONNECTED).when(mTelephonyManager).getDataState();
 
-        assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
+        assertTrue(TextUtils.equals(spyController.getSubtitleText(false),
+                getResourcesString("all_network_unavailable")));
+
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(spyController).getActiveAutoSwitchNonDdsSubId();
+        spyController.onAccessPointsChanged(null /* accessPoints */);
+        assertTrue(TextUtils.equals(spyController.getSubtitleText(false),
                 getResourcesString("all_network_unavailable")));
     }
 
@@ -651,6 +705,108 @@
     }
 
     @Test
+    public void getSignalStrengthIcon_differentSubId() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        InternetDialogController spyController = spy(mInternetDialogController);
+        Drawable icons = spyController.getSignalStrengthIcon(SUB_ID, mContext, 1, 1, 0, false);
+        Drawable icons2 = spyController.getSignalStrengthIcon(SUB_ID2, mContext, 1, 1, 0, false);
+
+        assertThat(icons).isNotEqualTo(icons2);
+    }
+
+    @Test
+    public void getActiveAutoSwitchNonDdsSubId() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        // active on non-DDS
+        SubscriptionInfo info = mock(SubscriptionInfo.class);
+        doReturn(SUB_ID2).when(info).getSubscriptionId();
+        when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info);
+
+        int subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+        assertThat(subId).isEqualTo(SUB_ID2);
+
+        // active on CBRS
+        doReturn(true).when(info).isOpportunistic();
+        subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+        assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+        // active on DDS
+        doReturn(false).when(info).isOpportunistic();
+        doReturn(SUB_ID).when(info).getSubscriptionId();
+        when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info);
+
+        subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+        assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    @Test
+    public void getActiveAutoSwitchNonDdsSubId_flagOff() {
+        // active on non-DDS
+        SubscriptionInfo info = mock(SubscriptionInfo.class);
+        doReturn(SUB_ID2).when(info).getSubscriptionId();
+        when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info);
+
+        int subId = mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+        assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    @Test
+    public void getMobileNetworkSummary() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        InternetDialogController spyController = spy(mInternetDialogController);
+        doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId();
+        doReturn(true).when(spyController).isMobileDataEnabled();
+        doReturn(true).when(spyController).activeNetworkIsCellular();
+        String dds = spyController.getMobileNetworkSummary(SUB_ID);
+        String nonDds = spyController.getMobileNetworkSummary(SUB_ID2);
+
+        assertThat(dds).contains(mContext.getString(R.string.mobile_data_poor_connection));
+        assertThat(dds).isNotEqualTo(nonDds);
+    }
+
+    @Test
+    public void getMobileNetworkSummary_flagOff() {
+        InternetDialogController spyController = spy(mInternetDialogController);
+        doReturn(true).when(spyController).isMobileDataEnabled();
+        doReturn(true).when(spyController).activeNetworkIsCellular();
+        String dds = spyController.getMobileNetworkSummary(SUB_ID);
+
+        assertThat(dds).contains(mContext.getString(R.string.mobile_data_connection_active));
+    }
+
+    @Test
+    public void launchMobileNetworkSettings_validSubId() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        InternetDialogController spyController = spy(mInternetDialogController);
+        doReturn(SUB_ID2).when(spyController).getActiveAutoSwitchNonDdsSubId();
+        spyController.launchMobileNetworkSettings(mDialogLaunchView);
+
+        verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt(),
+                any());
+    }
+
+    @Test
+    public void launchMobileNetworkSettings_invalidSubId() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        InternetDialogController spyController = spy(mInternetDialogController);
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(spyController).getActiveAutoSwitchNonDdsSubId();
+        spyController.launchMobileNetworkSettings(mDialogLaunchView);
+
+        verify(mActivityStarter, never())
+                .postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
+    }
+
+    @Test
+    public void setAutoDataSwitchMobileDataPolicy() {
+        mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+        mInternetDialogController.setAutoDataSwitchMobileDataPolicy(SUB_ID, true);
+
+        verify(mTelephonyManager).setMobileDataPolicyEnabled(eq(
+                TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH), eq(true));
+    }
+
+    @Test
     public void getSignalStrengthDrawableWithLevel_carrierNetworkIsNotActive_useMobileDataLevel() {
         // Fake mobile data level as SIGNAL_STRENGTH_POOR(1)
         when(mSignalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_POOR);
@@ -658,9 +814,9 @@
         when(mInternetDialogController.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX);
 
         InternetDialogController spyController = spy(mInternetDialogController);
-        spyController.getSignalStrengthDrawableWithLevel(false /* isCarrierNetworkActive */);
+        spyController.getSignalStrengthDrawableWithLevel(false /* isCarrierNetworkActive */, 0);
 
-        verify(spyController).getSignalStrengthIcon(any(), eq(SIGNAL_STRENGTH_POOR),
+        verify(spyController).getSignalStrengthIcon(eq(0), any(), eq(SIGNAL_STRENGTH_POOR),
                 eq(NUM_SIGNAL_STRENGTH_BINS), anyInt(), anyBoolean());
     }
 
@@ -672,9 +828,9 @@
         when(mInternetDialogController.getCarrierNetworkLevel()).thenReturn(WIFI_LEVEL_MAX);
 
         InternetDialogController spyController = spy(mInternetDialogController);
-        spyController.getSignalStrengthDrawableWithLevel(true /* isCarrierNetworkActive */);
+        spyController.getSignalStrengthDrawableWithLevel(true /* isCarrierNetworkActive */, 0);
 
-        verify(spyController).getSignalStrengthIcon(any(), eq(WIFI_LEVEL_MAX),
+        verify(spyController).getSignalStrengthIcon(eq(0), any(), eq(WIFI_LEVEL_MAX),
                 eq(WIFI_LEVEL_MAX + 1), anyInt(), anyBoolean());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index f922475..8c8fdc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -8,12 +8,15 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.AlertDialog;
+import android.content.DialogInterface;
 import android.os.Handler;
 import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
@@ -31,6 +34,7 @@
 import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -72,6 +76,8 @@
     private InternetDialogController mInternetDialogController;
     @Mock
     private KeyguardStateController mKeyguard;
+    @Mock
+    private DialogLaunchAnimator mDialogLaunchAnimator;
 
     private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock());
     private InternetDialog mInternetDialog;
@@ -100,8 +106,9 @@
         when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true);
         when(mWifiEntries.size()).thenReturn(1);
 
-        when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE);
-        when(mInternetDialogController.getMobileNetworkSummary())
+        when(mInternetDialogController.getMobileNetworkTitle(anyInt()))
+                .thenReturn(MOBILE_NETWORK_TITLE);
+        when(mInternetDialogController.getMobileNetworkSummary(anyInt()))
                 .thenReturn(MOBILE_NETWORK_SUMMARY);
         when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
 
@@ -115,7 +122,8 @@
 
     private void createInternetDialog() {
         mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
-                mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler,
+                mInternetDialogController, true, true, true, mock(UiEventLogger.class),
+                mDialogLaunchAnimator, mHandler,
                 mBgExecutor, mKeyguard);
         mInternetDialog.mAdapter = mInternetAdapter;
         mInternetDialog.mConnectedWifiEntry = mInternetWifiEntry;
@@ -307,12 +315,18 @@
 
     @Test
     public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() {
+        mInternetDialog.dismissDialog();
+        doReturn(true).when(mInternetDialogController).hasActiveSubId();
+        createInternetDialog();
         // The preconditions WiFi ON and Internet WiFi are already in setUp()
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
 
-        mInternetDialog.updateDialog(false);
+        mInternetDialog.updateDialog(true);
 
         assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+        LinearLayout secondaryLayout = mDialogView.requireViewById(
+                R.id.secondary_mobile_network_layout);
+        assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -460,6 +474,45 @@
     }
 
     @Test
+    public void updateDialog_showSecondaryDataSub() {
+        mInternetDialog.dismissDialog();
+        doReturn(1).when(mInternetDialogController).getActiveAutoSwitchNonDdsSubId();
+        doReturn(true).when(mInternetDialogController).hasActiveSubId();
+        doReturn(false).when(mInternetDialogController).isAirplaneModeEnabled();
+        createInternetDialog();
+
+        clearInvocations(mInternetDialogController);
+        mInternetDialog.updateDialog(true);
+
+        LinearLayout primaryLayout = mDialogView.requireViewById(
+                R.id.mobile_network_layout);
+        LinearLayout secondaryLayout = mDialogView.requireViewById(
+                R.id.secondary_mobile_network_layout);
+
+        verify(mInternetDialogController).getMobileNetworkSummary(1);
+        assertThat(primaryLayout.getBackground()).isNotEqualTo(secondaryLayout.getBackground());
+
+        // Tap the primary sub info
+        primaryLayout.performClick();
+        ArgumentCaptor<AlertDialog> dialogArgumentCaptor =
+                ArgumentCaptor.forClass(AlertDialog.class);
+        verify(mDialogLaunchAnimator).showFromDialog(dialogArgumentCaptor.capture(),
+                eq(mInternetDialog), eq(null), eq(false));
+        AlertDialog dialog = dialogArgumentCaptor.getValue();
+        dialog.show();
+        dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+        // TODO(b/253399304)
+        // TestableLooper.get(this).processAllMessages();
+        // verify(mInternetDialogController).setAutoDataSwitchMobileDataPolicy(1, false);
+
+        // Tap the secondary sub info
+        secondaryLayout.performClick();
+        verify(mInternetDialogController).launchMobileNetworkSettings(any(View.class));
+
+        dialog.dismiss();
+    }
+
+    @Test
     public void updateDialog_wifiOn_hideWifiScanNotify() {
         // The preconditions WiFi ON and WiFi entries are already in setUp()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
new file mode 100644
index 0000000..0aa3621
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenrecord
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.widget.Spinner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class ScreenRecordPermissionDialogTest : SysuiTestCase() {
+
+    @Mock private lateinit var starter: ActivityStarter
+    @Mock private lateinit var controller: RecordingController
+    @Mock private lateinit var userContextProvider: UserContextProvider
+    @Mock private lateinit var flags: FeatureFlags
+    @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+    @Mock private lateinit var onStartRecordingClicked: Runnable
+
+    private lateinit var dialog: ScreenRecordPermissionDialog
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        dialog =
+            ScreenRecordPermissionDialog(
+                context,
+                controller,
+                starter,
+                dialogLaunchAnimator,
+                userContextProvider,
+                onStartRecordingClicked
+            )
+        dialog.onCreate(null)
+        whenever(flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)).thenReturn(true)
+    }
+
+    @After
+    fun teardown() {
+        if (::dialog.isInitialized) {
+            dialog.dismiss()
+        }
+    }
+
+    @Test
+    fun testShowDialog_partialScreenSharingEnabled_optionsSpinnerIsVisible() {
+        dialog.show()
+
+        val visibility = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner).visibility
+        assertThat(visibility).isEqualTo(View.VISIBLE)
+    }
+
+    @Test
+    fun testShowDialog_singleAppSelected_showTapsIsGone() {
+        dialog.show()
+        onSpinnerItemSelected(SINGLE_APP)
+
+        val visibility = dialog.requireViewById<View>(R.id.show_taps).visibility
+        assertThat(visibility).isEqualTo(View.GONE)
+    }
+
+    @Test
+    fun testShowDialog_entireScreenSelected_showTapsIsVisible() {
+        dialog.show()
+        onSpinnerItemSelected(ENTIRE_SCREEN)
+
+        val visibility = dialog.requireViewById<View>(R.id.show_taps).visibility
+        assertThat(visibility).isEqualTo(View.VISIBLE)
+    }
+
+    private fun onSpinnerItemSelected(position: Int) {
+        val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
+        spinner.onItemSelectedListener.onItemSelected(spinner, mock(), position, /* id= */ 0)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 8c9404e..85c8ba7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -184,7 +184,7 @@
                         ActionTransition::new, mSmartActionsProvider);
 
         Notification.Action shareAction = task.createShareAction(mContext, mContext.getResources(),
-                Uri.parse("Screenshot_123.png")).get().action;
+                Uri.parse("Screenshot_123.png"), true).get().action;
 
         Intent intent = shareAction.actionIntent.getIntent();
         assertNotNull(intent);
@@ -212,7 +212,7 @@
                         ActionTransition::new, mSmartActionsProvider);
 
         Notification.Action editAction = task.createEditAction(mContext, mContext.getResources(),
-                Uri.parse("Screenshot_123.png")).get().action;
+                Uri.parse("Screenshot_123.png"), true).get().action;
 
         Intent intent = editAction.actionIntent.getIntent();
         assertNotNull(intent);
@@ -241,7 +241,7 @@
 
         Notification.Action deleteAction = task.createDeleteAction(mContext,
                 mContext.getResources(),
-                Uri.parse("Screenshot_123.png"));
+                Uri.parse("Screenshot_123.png"), true);
 
         Intent intent = deleteAction.actionIntent.getIntent();
         assertNotNull(intent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
deleted file mode 100644
index 1b515c6..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
+++ /dev/null
@@ -1,74 +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.settings;
-
-import android.content.Intent;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Testing functionality of the current user tracker
- */
-@SmallTest
-public class CurrentUserTrackerTest extends SysuiTestCase {
-
-    private CurrentUserTracker mTracker;
-    private CurrentUserTracker.UserReceiver mReceiver;
-    @Mock
-    private BroadcastDispatcher mBroadcastDispatcher;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mReceiver = new CurrentUserTracker.UserReceiver(mBroadcastDispatcher);
-        mTracker = new CurrentUserTracker(mReceiver) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                stopTracking();
-            }
-        };
-    }
-
-    @Test
-    public void testBroadCastDoesntCrashOnConcurrentModification() {
-        mTracker.startTracking();
-        CurrentUserTracker secondTracker = new CurrentUserTracker(mReceiver) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                stopTracking();
-            }
-        };
-        secondTracker.startTracking();
-        triggerUserSwitch();
-    }
-    /**
-     * Simulates a user switch event.
-     */
-    private void triggerUserSwitch() {
-        Intent intent = new Intent(Intent.ACTION_USER_SWITCHED);
-        intent.putExtra(Intent.EXTRA_USER_HANDLE, 1);
-        mReceiver.onReceive(getContext(), intent);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
index 1130bda..9d1802a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
@@ -28,9 +28,10 @@
 import androidx.test.runner.intercepting.SingleActivityFactory
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
 import org.junit.After
 import org.junit.Before
 import org.junit.Rule
@@ -45,7 +46,9 @@
 @TestableLooper.RunWithLooper
 class BrightnessDialogTest : SysuiTestCase() {
 
+    @Mock private lateinit var userTracker: UserTracker
     @Mock private lateinit var brightnessSliderControllerFactory: BrightnessSliderController.Factory
+    @Mock private lateinit var mainExecutor: Executor
     @Mock private lateinit var backgroundHandler: Handler
     @Mock private lateinit var brightnessSliderController: BrightnessSliderController
 
@@ -56,8 +59,9 @@
             object : SingleActivityFactory<TestDialog>(TestDialog::class.java) {
                 override fun create(intent: Intent?): TestDialog {
                     return TestDialog(
-                        fakeBroadcastDispatcher,
+                        userTracker,
                         brightnessSliderControllerFactory,
+                        mainExecutor,
                         backgroundHandler
                     )
                 }
@@ -100,8 +104,15 @@
     }
 
     class TestDialog(
-        broadcastDispatcher: BroadcastDispatcher,
+        userTracker: UserTracker,
         brightnessSliderControllerFactory: BrightnessSliderController.Factory,
+        mainExecutor: Executor,
         backgroundHandler: Handler
-    ) : BrightnessDialog(broadcastDispatcher, brightnessSliderControllerFactory, backgroundHandler)
+    ) :
+        BrightnessDialog(
+            userTracker,
+            brightnessSliderControllerFactory,
+            mainExecutor,
+            backgroundHandler
+        )
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
index 0ce9056..bc17c19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -320,6 +321,64 @@
         assertThat(changes.largeScreenConstraintsChanges).isNull()
     }
 
+    @Test
+    fun testRelevantViewsAreNotMatchConstraints() {
+        val views = mapOf(
+                R.id.clock to "clock",
+                R.id.date to "date",
+                R.id.statusIcons to "icons",
+                R.id.privacy_container to "privacy",
+                R.id.carrier_group to "carriers",
+                R.id.batteryRemainingIcon to "battery",
+        )
+        views.forEach { (id, name) ->
+            assertWithMessage("$name has 0 height in qqs")
+                    .that(qqsConstraint.getConstraint(id).layout.mHeight).isNotEqualTo(0)
+            assertWithMessage("$name has 0 width in qqs")
+                    .that(qqsConstraint.getConstraint(id).layout.mWidth).isNotEqualTo(0)
+            assertWithMessage("$name has 0 height in qs")
+                    .that(qsConstraint.getConstraint(id).layout.mHeight).isNotEqualTo(0)
+            assertWithMessage("$name has 0 width in qs")
+                    .that(qsConstraint.getConstraint(id).layout.mWidth).isNotEqualTo(0)
+        }
+    }
+
+    @Test
+    fun testCheckViewsDontChangeSizeBetweenAnimationConstraints() {
+        val views = mapOf(
+                R.id.clock to "clock",
+                R.id.date to "date",
+                R.id.statusIcons to "icons",
+                R.id.privacy_container to "privacy",
+                R.id.carrier_group to "carriers",
+                R.id.batteryRemainingIcon to "battery",
+        )
+        views.forEach { (id, name) ->
+            assertWithMessage("$name changes height")
+                    .that(qqsConstraint.getConstraint(id).layout.mHeight)
+                    .isEqualTo(qsConstraint.getConstraint(id).layout.mHeight)
+            assertWithMessage("$name changes width")
+                    .that(qqsConstraint.getConstraint(id).layout.mWidth)
+                    .isEqualTo(qsConstraint.getConstraint(id).layout.mWidth)
+        }
+    }
+
+    @Test
+    fun testEmptyCutoutDateIconsAreConstrainedWidth() {
+        CombinedShadeHeadersConstraintManagerImpl.emptyCutoutConstraints()()
+
+        assertThat(qqsConstraint.getConstraint(R.id.date).layout.constrainedWidth).isTrue()
+        assertThat(qqsConstraint.getConstraint(R.id.statusIcons).layout.constrainedWidth).isTrue()
+    }
+
+    @Test
+    fun testCenterCutoutDateIconsAreConstrainedWidth() {
+        CombinedShadeHeadersConstraintManagerImpl.centerCutoutConstraints(false, 10)()
+
+        assertThat(qqsConstraint.getConstraint(R.id.date).layout.constrainedWidth).isTrue()
+        assertThat(qqsConstraint.getConstraint(R.id.statusIcons).layout.constrainedWidth).isTrue()
+    }
+
     private operator fun ConstraintsChanges.invoke() {
         qqsConstraintsChanges?.invoke(qqsConstraint)
         qsConstraintsChanges?.invoke(qsConstraint)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 1f71e3c..69a4559 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -94,7 +94,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.camera.CameraGestureHelper;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.doze.DozeLog;
@@ -134,6 +133,7 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
@@ -199,6 +199,7 @@
     @Mock private KeyguardBottomAreaView mQsFrame;
     @Mock private HeadsUpManagerPhone mHeadsUpManager;
     @Mock private NotificationShelfController mNotificationShelfController;
+    @Mock private NotificationGutsManager mGutsManager;
     @Mock private KeyguardStatusBarView mKeyguardStatusBar;
     @Mock private KeyguardUserSwitcherView mUserSwitcherView;
     @Mock private ViewStub mUserSwitcherStubView;
@@ -454,6 +455,7 @@
                 () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
                 mConversationNotificationManager, mMediaHierarchyManager,
                 mStatusBarKeyguardViewManager,
+                mGutsManager,
                 mNotificationsQSContainerController,
                 mNotificationStackScrollLayoutController,
                 mKeyguardStatusViewComponentFactory,
@@ -492,7 +494,6 @@
                 mUnlockedScreenOffAnimationController,
                 mShadeTransitionController,
                 systemClock,
-                mock(CameraGestureHelper.class),
                 mKeyguardBottomAreaViewModel,
                 mKeyguardBottomAreaInteractor,
                 mDumpManager);
@@ -756,6 +757,8 @@
 
     @Test
     public void testOnTouchEvent_expansionResumesAfterBriefTouch() {
+        mFalsingManager.setIsClassifierEnabled(true);
+        mFalsingManager.setIsFalseTouch(false);
         // Start shade collapse with swipe up
         onTouchEvent(MotionEvent.obtain(0L /* downTime */,
                 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -1121,6 +1124,19 @@
     }
 
     @Test
+    public void testUnlockedSplitShadeTransitioningToKeyguard_closesQS() {
+        enableSplitShade(true);
+        mStatusBarStateController.setState(SHADE);
+        mNotificationPanelViewController.setQsExpanded(true);
+
+        mStatusBarStateController.setState(KEYGUARD);
+
+
+        assertThat(mNotificationPanelViewController.isQsExpanded()).isEqualTo(false);
+        assertThat(mNotificationPanelViewController.isQsExpandImmediate()).isEqualTo(false);
+    }
+
+    @Test
     public void testSwitchesToCorrectClockInSinglePaneShade() {
         mStatusBarStateController.setState(KEYGUARD);
 
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 db7e017..c3207c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -33,6 +33,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
+import com.android.systemui.statusbar.NotificationInsetsController
 import com.android.systemui.statusbar.NotificationShadeDepthController
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
@@ -94,6 +95,8 @@
     private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
     @Mock
     private lateinit var pulsingGestureListener: PulsingGestureListener
+    @Mock
+    private lateinit var notificationInsetsController: NotificationInsetsController
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerContainer: ViewGroup
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@@ -124,6 +127,7 @@
             centralSurfaces,
             notificationShadeWindowController,
             keyguardUnlockAnimationController,
+            notificationInsetsController,
             ambientState,
             pulsingGestureListener,
             featureFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index a6c80ab6..4bf00c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationInsetsController;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -91,6 +92,7 @@
     @Mock private FeatureFlags mFeatureFlags;
     @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
     @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+    @Mock private NotificationInsetsController mNotificationInsetsController;
 
     @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
             mInteractionEventHandlerCaptor;
@@ -125,6 +127,7 @@
                 mCentralSurfaces,
                 mNotificationShadeWindowController,
                 mKeyguardUnlockAnimationController,
+                mNotificationInsetsController,
                 mAmbientState,
                 mPulsingGestureListener,
                 mFeatureFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index 539a54b..a7588dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -43,6 +43,7 @@
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.notNull
 import org.mockito.Mock
+import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
@@ -139,12 +140,19 @@
     }
 
     @Test
-    fun defaultClock_events_onFontSettingChanged() {
+    fun defaultSmallClock_events_onFontSettingChanged() {
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
-        clock.events.onFontSettingChanged()
+        clock.smallClock.events.onFontSettingChanged(100f)
 
-        verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
-        verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
+        verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), eq(100f))
+    }
+
+    @Test
+    fun defaultLargeClock_events_onFontSettingChanged() {
+        val clock = provider.createClock(DEFAULT_CLOCK_ID)
+        clock.largeClock.events.onFontSettingChanged(200f)
+
+        verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), eq(200f))
         verify(mockLargeClockView).setLayoutParams(any())
     }
 
@@ -171,4 +179,12 @@
         verify(mockSmallClockView, times(2)).refreshFormat()
         verify(mockLargeClockView, times(2)).refreshFormat()
     }
+
+    @Test
+    fun test_aodClock_always_whiteColor() {
+        val clock = provider.createClock(DEFAULT_CLOCK_ID)
+        clock.animations.doze(0.9f) // set AOD mode to active
+        clock.smallClock.events.onRegionDarknessChanged(true)
+        verify((clock.smallClock.view as AnimatableClockView), never()).animateAppearOnLockscreen()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 9b17cc2..c280ec8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -32,12 +32,12 @@
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO;
-import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_RESTING;
+import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
-import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF;
 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
+import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_TURNING_ON;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -87,6 +87,8 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.TrustGrantFlags;
+import com.android.keyguard.logging.KeyguardLogger;
 import com.android.settingslib.fuelgauge.BatteryStatus;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
@@ -271,7 +273,7 @@
                 mUserManager, mExecutor, mExecutor, mFalsingManager,
                 mAuthController, mLockPatternUtils, mScreenLifecycle,
                 mKeyguardBypassController, mAccessibilityManager,
-                mFaceHelpMessageDeferral);
+                mFaceHelpMessageDeferral, mock(KeyguardLogger.class));
         mController.init();
         mController.setIndicationArea(mIndicationArea);
         verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
@@ -828,31 +830,6 @@
     }
 
     @Test
-    public void updateMonitor_listenerUpdatesIndication() {
-        createController();
-        String restingIndication = "Resting indication";
-        reset(mKeyguardUpdateMonitor);
-
-        mController.setVisible(true);
-        verifyIndicationMessage(INDICATION_TYPE_USER_LOCKED,
-                mContext.getString(com.android.internal.R.string.lockscreen_storage_locked));
-
-        reset(mRotateTextViewController);
-        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
-        when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
-        mController.setRestingIndication(restingIndication);
-        verifyHideIndication(INDICATION_TYPE_USER_LOCKED);
-        verifyIndicationMessage(INDICATION_TYPE_RESTING, restingIndication);
-
-        reset(mRotateTextViewController);
-        reset(mKeyguardUpdateMonitor);
-        when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
-        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
-        mKeyguardStateControllerCallback.onUnlockedChanged();
-        verifyIndicationMessage(INDICATION_TYPE_RESTING, restingIndication);
-    }
-
-    @Test
     public void onRefreshBatteryInfo_computesChargingTime() throws RemoteException {
         createController();
         BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
@@ -1064,7 +1041,8 @@
 
         // GIVEN a trust granted message but trust isn't granted
         final String trustGrantedMsg = "testing trust granted message";
-        mController.getKeyguardCallback().showTrustGrantedMessage(trustGrantedMsg);
+        mController.getKeyguardCallback().onTrustGrantedForCurrentUser(
+                false, new TrustGrantFlags(0), trustGrantedMsg);
 
         verifyHideIndication(INDICATION_TYPE_TRUST);
 
@@ -1088,7 +1066,8 @@
 
         // WHEN the showTrustGranted method is called
         final String trustGrantedMsg = "testing trust granted message";
-        mController.getKeyguardCallback().showTrustGrantedMessage(trustGrantedMsg);
+        mController.getKeyguardCallback().onTrustGrantedForCurrentUser(
+                false, new TrustGrantFlags(0), trustGrantedMsg);
 
         // THEN verify the trust granted message shows
         verifyIndicationMessage(
@@ -1105,7 +1084,8 @@
         when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
 
         // WHEN the showTrustGranted method is called with a null message
-        mController.getKeyguardCallback().showTrustGrantedMessage(null);
+        mController.getKeyguardCallback().onTrustGrantedForCurrentUser(
+                false, new TrustGrantFlags(0), null);
 
         // THEN verify the default trust granted message shows
         verifyIndicationMessage(
@@ -1122,7 +1102,8 @@
         when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
 
         // WHEN the showTrustGranted method is called with an EMPTY string
-        mController.getKeyguardCallback().showTrustGrantedMessage("");
+        mController.getKeyguardCallback().onTrustGrantedForCurrentUser(
+                false, new TrustGrantFlags(0), "");
 
         // THEN verify NO trust message is shown
         verifyNoMessage(INDICATION_TYPE_TRUST);
@@ -1418,6 +1399,21 @@
     }
 
     @Test
+    public void onBiometricError_faceLockedOutSecondTimeOnBouncer_showsUnavailableMessage() {
+        createController();
+        onFaceLockoutError("first lockout");
+        clearInvocations(mRotateTextViewController);
+        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
+
+        onFaceLockoutError("second lockout");
+
+        verify(mStatusBarKeyguardViewManager)
+                .setKeyguardMessage(
+                        eq(mContext.getString(R.string.keyguard_face_unlock_unavailable)),
+                        any());
+    }
+
+    @Test
     public void onBiometricError_faceLockedOutSecondTimeButUdfpsActive_showsNoMessage() {
         createController();
         onFaceLockoutError("first lockout");
@@ -1469,6 +1465,44 @@
     }
 
     @Test
+    public void onFpLockoutStateChanged_whenFpIsLockedOut_showsPersistentMessage() {
+        createController();
+        mController.setVisible(true);
+        when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(true);
+
+        mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+
+        verifyIndicationShown(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
+    public void onFpLockoutStateChanged_whenFpIsNotLockedOut_showsPersistentMessage() {
+        createController();
+        mController.setVisible(true);
+        clearInvocations(mRotateTextViewController);
+        when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(false);
+
+        mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+
+        verifyHideIndication(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE);
+    }
+
+    @Test
+    public void onVisibilityChange_showsPersistentMessage_ifFpIsLockedOut() {
+        createController();
+        mController.setVisible(false);
+        when(mKeyguardUpdateMonitor.isFingerprintLockedOut()).thenReturn(true);
+        mKeyguardUpdateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+        clearInvocations(mRotateTextViewController);
+
+        mController.setVisible(true);
+
+        verifyIndicationShown(INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
     public void onBiometricError_whenFaceIsLocked_onMultipleLockOutErrors_showUnavailableMessage() {
         createController();
         onFaceLockoutError("first lockout");
@@ -1482,6 +1516,44 @@
                 mContext.getString(R.string.keyguard_face_unlock_unavailable));
     }
 
+    @Test
+    public void onBiometricError_screenIsTurningOn_faceLockedOutFpIsNotAvailable_showsMessage() {
+        createController();
+        screenIsTurningOn();
+        fingerprintUnlockIsNotPossible();
+
+        onFaceLockoutError("lockout error");
+        verifyNoMoreInteractions(mRotateTextViewController);
+
+        mScreenObserver.onScreenTurnedOn();
+
+        verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE,
+                "lockout error");
+        verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
+    public void onBiometricError_screenIsTurningOn_faceLockedOutFpIsAvailable_showsMessage() {
+        createController();
+        screenIsTurningOn();
+        fingerprintUnlockIsPossible();
+
+        onFaceLockoutError("lockout error");
+        verifyNoMoreInteractions(mRotateTextViewController);
+
+        mScreenObserver.onScreenTurnedOn();
+
+        verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE,
+                "lockout error");
+        verifyIndicationShown(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                mContext.getString(R.string.keyguard_suggest_fingerprint));
+    }
+
+    private void screenIsTurningOn() {
+        when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_TURNING_ON);
+    }
+
     private void sendUpdateDisclosureBroadcast() {
         mBroadcastReceiver.onReceive(mContext, new Intent());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index bdafa48..15a687d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -53,6 +53,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -78,6 +79,8 @@
     private NotificationPresenter mPresenter;
     @Mock
     private UserManager mUserManager;
+    @Mock
+    private UserTracker mUserTracker;
 
     // Dependency mocks:
     @Mock
@@ -115,6 +118,7 @@
         MockitoAnnotations.initMocks(this);
 
         int currentUserId = ActivityManager.getCurrentUser();
+        when(mUserTracker.getUserId()).thenReturn(currentUserId);
         mSettings = new FakeSettings();
         mSettings.setUserId(ActivityManager.getCurrentUser());
         mCurrentUser = new UserInfo(currentUserId, "", 0);
@@ -344,6 +348,7 @@
                     mBroadcastDispatcher,
                     mDevicePolicyManager,
                     mUserManager,
+                    mUserTracker,
                     (() -> mVisibilityProvider),
                     (() -> mNotifCollection),
                     mClickNotifier,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt
new file mode 100644
index 0000000..62b4e7b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.connectivity
+
+import android.content.res.Resources
+import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
+
+typealias CarrierId = Int
+
+typealias NetworkType = String
+
+typealias ResId = Int
+
+class MobileIconCarrierIdOverridesFake : MobileIconCarrierIdOverrides {
+    /** Backing for [carrierIdEntryExists] */
+    var overriddenIds = mutableSetOf<Int>()
+
+    /** Backing for [getOverrideFor]. Map should be Map< CarrierId < NetworkType, ResId>> */
+    var overridesByCarrierId = mutableMapOf<CarrierId, Map<NetworkType, ResId>>()
+
+    override fun getOverrideFor(
+        carrierId: CarrierId,
+        networkType: NetworkType,
+        resources: Resources
+    ): ResId {
+        if (!overriddenIds.contains(carrierId)) return 0
+
+        return overridesByCarrierId[carrierId]?.get(networkType) ?: 0
+    }
+
+    override fun carrierIdEntryExists(carrierId: Int): Boolean {
+        return overriddenIds.contains(carrierId)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java
deleted file mode 100644
index 7ddfde3..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.connectivity;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-
-import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class MobileStateTest extends SysuiTestCase {
-
-    private final MobileState mState = new MobileState();
-
-    @Before
-    public void setUp() {
-    }
-
-    @Test
-    public void testIsDataDisabledOrNotDefault_dataDisabled() {
-        mState.iconGroup = TelephonyIcons.DATA_DISABLED;
-        mState.userSetup = true;
-
-        assertTrue(mState.isDataDisabledOrNotDefault());
-    }
-
-    @Test
-    public void testIsDataDisabledOrNotDefault_notDefaultData() {
-        mState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
-        mState.userSetup = true;
-
-        assertTrue(mState.isDataDisabledOrNotDefault());
-    }
-
-    @Test
-    public void testIsDataDisabledOrNotDefault_notDisabled() {
-        mState.iconGroup = TelephonyIcons.G;
-        mState.userSetup = true;
-
-        assertFalse(mState.isDataDisabledOrNotDefault());
-    }
-
-    @Test
-    public void testHasActivityIn_noData_noActivity() {
-        mState.dataConnected = false;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityIn = false;
-
-        assertFalse(mState.hasActivityIn());
-    }
-
-    @Test
-    public void testHasActivityIn_noData_activityIn() {
-        mState.dataConnected = false;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityIn = true;
-
-        assertFalse(mState.hasActivityIn());
-    }
-
-    @Test
-    public void testHasActivityIn_dataConnected_activityIn() {
-        mState.dataConnected = true;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityIn = true;
-
-        assertTrue(mState.hasActivityIn());
-    }
-
-    @Test
-    public void testHasActivityIn_carrierNetworkChange() {
-        mState.dataConnected = true;
-        mState.carrierNetworkChangeMode = true;
-        mState.activityIn = true;
-
-        assertFalse(mState.hasActivityIn());
-    }
-
-    @Test
-    public void testHasActivityOut_noData_noActivity() {
-        mState.dataConnected = false;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityOut = false;
-
-        assertFalse(mState.hasActivityOut());
-    }
-
-    @Test
-    public void testHasActivityOut_noData_activityOut() {
-        mState.dataConnected = false;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityOut = true;
-
-        assertFalse(mState.hasActivityOut());
-    }
-
-    @Test
-    public void testHasActivityOut_dataConnected_activityOut() {
-        mState.dataConnected = true;
-        mState.carrierNetworkChangeMode = false;
-        mState.activityOut = true;
-
-        assertTrue(mState.hasActivityOut());
-    }
-
-    @Test
-    public void testHasActivityOut_carrierNetworkChange() {
-        mState.dataConnected = true;
-        mState.carrierNetworkChangeMode = true;
-        mState.activityOut = true;
-
-        assertFalse(mState.hasActivityOut());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt
new file mode 100644
index 0000000..a226ded
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.connectivity
+
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import com.android.settingslib.mobile.TelephonyIcons
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class MobileStateTest : SysuiTestCase() {
+
+    private val state = MobileState()
+    @Before fun setUp() {}
+
+    @Test
+    fun testIsDataDisabledOrNotDefault_dataDisabled() {
+        state.iconGroup = TelephonyIcons.DATA_DISABLED
+        state.userSetup = true
+        assertTrue(state.isDataDisabledOrNotDefault)
+    }
+
+    @Test
+    fun testIsDataDisabledOrNotDefault_notDefaultData() {
+        state.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA
+        state.userSetup = true
+        assertTrue(state.isDataDisabledOrNotDefault)
+    }
+
+    @Test
+    fun testIsDataDisabledOrNotDefault_notDisabled() {
+        state.iconGroup = TelephonyIcons.G
+        state.userSetup = true
+        assertFalse(state.isDataDisabledOrNotDefault)
+    }
+
+    @Test
+    fun testHasActivityIn_noData_noActivity() {
+        state.dataConnected = false
+        state.carrierNetworkChangeMode = false
+        state.activityIn = false
+        assertFalse(state.hasActivityIn())
+    }
+
+    @Test
+    fun testHasActivityIn_noData_activityIn() {
+        state.dataConnected = false
+        state.carrierNetworkChangeMode = false
+        state.activityIn = true
+        assertFalse(state.hasActivityIn())
+    }
+
+    @Test
+    fun testHasActivityIn_dataConnected_activityIn() {
+        state.dataConnected = true
+        state.carrierNetworkChangeMode = false
+        state.activityIn = true
+        assertTrue(state.hasActivityIn())
+    }
+
+    @Test
+    fun testHasActivityIn_carrierNetworkChange() {
+        state.dataConnected = true
+        state.carrierNetworkChangeMode = true
+        state.activityIn = true
+        assertFalse(state.hasActivityIn())
+    }
+
+    @Test
+    fun testHasActivityOut_noData_noActivity() {
+        state.dataConnected = false
+        state.carrierNetworkChangeMode = false
+        state.activityOut = false
+        assertFalse(state.hasActivityOut())
+    }
+
+    @Test
+    fun testHasActivityOut_noData_activityOut() {
+        state.dataConnected = false
+        state.carrierNetworkChangeMode = false
+        state.activityOut = true
+        assertFalse(state.hasActivityOut())
+    }
+
+    @Test
+    fun testHasActivityOut_dataConnected_activityOut() {
+        state.dataConnected = true
+        state.carrierNetworkChangeMode = false
+        state.activityOut = true
+        assertTrue(state.hasActivityOut())
+    }
+
+    @Test
+    fun testHasActivityOut_carrierNetworkChange() {
+        state.dataConnected = true
+        state.carrierNetworkChangeMode = true
+        state.activityOut = true
+        assertFalse(state.hasActivityOut())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 9c65fac..faf4592 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -71,6 +71,8 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -115,6 +117,7 @@
     protected TelephonyManager mMockTm;
     protected TelephonyListenerManager mTelephonyListenerManager;
     protected BroadcastDispatcher mMockBd;
+    protected UserTracker mUserTracker;
     protected Config mConfig;
     protected CallbackHandler mCallbackHandler;
     protected SubscriptionDefaults mMockSubDefaults;
@@ -125,6 +128,8 @@
     protected CarrierConfigTracker mCarrierConfigTracker;
     protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     protected Handler mMainHandler;
+    // Use a real mobile mappings object since lots of tests rely on it
+    protected FakeMobileMappingsProxy mMobileMappingsProxy = new FakeMobileMappingsProxy();
     protected WifiStatusTrackerFactory mWifiStatusTrackerFactory;
     protected MobileSignalControllerFactory mMobileFactory;
 
@@ -169,6 +174,7 @@
         mMockSm = mock(SubscriptionManager.class);
         mMockCm = mock(ConnectivityManager.class);
         mMockBd = mock(BroadcastDispatcher.class);
+        mUserTracker = mock(UserTracker.class);
         mMockNsm = mock(NetworkScoreManager.class);
         mMockSubDefaults = mock(SubscriptionDefaults.class);
         mCarrierConfigTracker = mock(CarrierConfigTracker.class);
@@ -219,10 +225,13 @@
 
         mWifiStatusTrackerFactory = new WifiStatusTrackerFactory(
                 mContext, mMockWm, mMockNsm, mMockCm, mMainHandler);
+        // Most of these tests rely on the actual MobileMappings behavior
+        mMobileMappingsProxy.setUseRealImpl(true);
         mMobileFactory = new MobileSignalControllerFactory(
                 mContext,
                 mCallbackHandler,
-                mCarrierConfigTracker
+                mCarrierConfigTracker,
+                mMobileMappingsProxy
         );
 
         mNetworkController = new NetworkControllerImpl(mContext,
@@ -240,6 +249,7 @@
                 mMockSubDefaults,
                 mMockProvisionController,
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mCarrierConfigTracker,
                 mWifiStatusTrackerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
index 4bed4a1..ca75a40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
@@ -18,12 +18,21 @@
 
 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
 import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import static android.telephony.TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED;
+import static android.telephony.TelephonyManager.EXTRA_CARRIER_ID;
+import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;
 
+import static com.android.settingslib.mobile.TelephonyIcons.NR_5G_PLUS;
+
+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.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.content.Intent;
 import android.net.NetworkCapabilities;
 import android.os.Handler;
 import android.os.Looper;
@@ -35,6 +44,7 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
+import com.android.settingslib.SignalIcon.MobileIconGroup;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.dump.DumpManager;
@@ -45,6 +55,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.HashMap;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
@@ -142,6 +154,7 @@
                 mMockSubDefaults,
                 mock(DeviceProvisionedController.class),
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mock(CarrierConfigTracker.class),
                 mWifiStatusTrackerFactory,
@@ -329,6 +342,57 @@
         assertFalse(mNetworkController.isMobileDataNetworkInService());
     }
 
+    @Test
+    public void mobileSignalController_getsCarrierId() {
+        when(mMockTm.getSimCarrierId()).thenReturn(1);
+        setupDefaultSignal();
+
+        assertEquals(1, mMobileSignalController.getState().getCarrierId());
+    }
+
+    @Test
+    public void mobileSignalController_updatesCarrierId_onChange() {
+        when(mMockTm.getSimCarrierId()).thenReturn(1);
+        setupDefaultSignal();
+
+        // Updates are sent down through this broadcast, we can send the intent directly
+        Intent intent = new Intent(ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
+        intent.putExtra(EXTRA_SUBSCRIPTION_ID, mSubId);
+        intent.putExtra(EXTRA_CARRIER_ID, 2);
+
+        mMobileSignalController.handleBroadcast(intent);
+
+        assertEquals(2, mMobileSignalController.getState().getCarrierId());
+    }
+
+    @Test
+    public void networkTypeIcon_hasCarrierIdOverride() {
+        int fakeCarrier = 1;
+        int fakeIconOverride = 12345;
+        int testDataNetType = 100;
+        String testDataString = "100";
+        HashMap<String, MobileIconGroup> testMap = new HashMap<>();
+        testMap.put(testDataString, NR_5G_PLUS);
+
+        // Pretend that there is an override for this icon, and this carrier ID
+        NetworkTypeResIdCache mockCache = mock(NetworkTypeResIdCache.class);
+        when(mockCache.get(eq(NR_5G_PLUS), eq(fakeCarrier), any())).thenReturn(fakeIconOverride);
+
+        // Turn off the default mobile mapping, so we can override
+        mMobileMappingsProxy.setUseRealImpl(false);
+        mMobileMappingsProxy.setIconMap(testMap);
+        // Use the mocked cache
+        mMobileSignalController.mCurrentState.setNetworkTypeResIdCache(mockCache);
+        // Rebuild the network map
+        mMobileSignalController.setConfiguration(mConfig);
+        when(mMockTm.getSimCarrierId()).thenReturn(fakeCarrier);
+
+        setupDefaultSignal();
+        updateDataConnectionState(TelephonyManager.DATA_CONNECTED, testDataNetType);
+
+        verifyDataIndicators(fakeIconOverride);
+    }
+
     private void testDataActivity(int direction, boolean in, boolean out) {
         updateDataActivity(direction);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
index d5f5105..84c242c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
@@ -82,6 +82,7 @@
                 mMockSubDefaults,
                 mMockProvisionController,
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mCarrierConfigTracker,
                 mWifiStatusTrackerFactory,
@@ -118,6 +119,7 @@
                 mMockSubDefaults,
                 mMockProvisionController,
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mCarrierConfigTracker,
                 mWifiStatusTrackerFactory,
@@ -152,6 +154,7 @@
                 mMockSubDefaults,
                 mock(DeviceProvisionedController.class),
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mock(CarrierConfigTracker.class),
                 mWifiStatusTrackerFactory,
@@ -189,6 +192,7 @@
                 mMockSubDefaults,
                 mock(DeviceProvisionedController.class),
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mock(CarrierConfigTracker.class),
                 mWifiStatusTrackerFactory,
@@ -274,6 +278,7 @@
                 mMockSubDefaults,
                 mock(DeviceProvisionedController.class),
                 mMockBd,
+                mUserTracker,
                 mDemoModeController,
                 mock(CarrierConfigTracker.class),
                 mWifiStatusTrackerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
new file mode 100644
index 0000000..9e73487
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.connectivity
+
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import com.android.settingslib.SignalIcon.MobileIconGroup
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class NetworkTypeResIdCacheTest : SysuiTestCase() {
+    private lateinit var cache: NetworkTypeResIdCache
+    private var overrides = MobileIconCarrierIdOverridesFake()
+
+    @Before
+    fun setUp() {
+        cache = NetworkTypeResIdCache(overrides)
+    }
+
+    @Test
+    fun carrier1_noOverride_usesDefault() {
+        assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconDefault1)
+    }
+
+    @Test
+    fun carrier1_overridden_usesOverride() {
+        overrides.overriddenIds.add(CARRIER_1)
+        overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
+
+        assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconOverride1)
+    }
+
+    @Test
+    fun carrier1_override_carrier2UsesDefault() {
+        overrides.overriddenIds.add(CARRIER_1)
+        overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
+
+        assertThat(cache.get(group1, CARRIER_2, context)).isEqualTo(iconDefault1)
+    }
+
+    @Test
+    fun carrier1_overrideType1_type2UsesDefault() {
+        overrides.overriddenIds.add(CARRIER_1)
+        overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
+
+        assertThat(cache.get(group2, CARRIER_1, context)).isEqualTo(iconDefault2)
+    }
+
+    companion object {
+        // Simplified icon overrides here
+        const val CARRIER_1 = 1
+        const val CARRIER_2 = 2
+
+        const val NET_TYPE_1 = "one"
+        const val iconDefault1 = 123
+        const val iconOverride1 = 321
+        val group1 = MobileIconGroup(NET_TYPE_1, /* dataContentDesc */ 0, iconDefault1)
+
+        const val NET_TYPE_2 = "two"
+        const val iconDefault2 = 234
+
+        val group2 = MobileIconGroup(NET_TYPE_2, /* dataContentDesc*/ 0, iconDefault2)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
index 7e2e6f6..bdedd24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
@@ -13,57 +13,55 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.statusbar.notification.collection.coordinator
 
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
 import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
 import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.withArgCaptor
-import java.util.function.Consumer
-import org.junit.Before
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.verify
+import java.util.function.Consumer
+import kotlin.time.Duration.Companion.seconds
 import org.mockito.Mockito.`when` as whenever
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 class KeyguardCoordinatorTest : SysuiTestCase() {
-    private val notifPipeline: NotifPipeline = mock()
+
     private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
+    private val keyguardRepository = FakeKeyguardRepository()
+    private val notifPipelineFlags: NotifPipelineFlags = mock()
+    private val notifPipeline: NotifPipeline = mock()
     private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider = mock()
     private val statusBarStateController: StatusBarStateController = mock()
 
-    private lateinit var onStateChangeListener: Consumer<String>
-    private lateinit var keyguardFilter: NotifFilter
-
-    @Before
-    fun setup() {
-        val keyguardCoordinator = KeyguardCoordinator(
-            keyguardNotifVisibilityProvider,
-            sectionHeaderVisibilityProvider,
-            statusBarStateController
-        )
-        keyguardCoordinator.attach(notifPipeline)
-        onStateChangeListener = withArgCaptor {
-            verify(keyguardNotifVisibilityProvider).addOnStateChangedListener(capture())
-        }
-        keyguardFilter = withArgCaptor {
-            verify(notifPipeline).addFinalizeFilter(capture())
-        }
-    }
-
     @Test
-    fun testSetSectionHeadersVisibleInShade() {
+    fun testSetSectionHeadersVisibleInShade() = runKeyguardCoordinatorTest {
         clearInvocations(sectionHeaderVisibilityProvider)
         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
         onStateChangeListener.accept("state change")
@@ -71,10 +69,176 @@
     }
 
     @Test
-    fun testSetSectionHeadersNotVisibleOnKeyguard() {
+    fun testSetSectionHeadersNotVisibleOnKeyguard() = runKeyguardCoordinatorTest {
         clearInvocations(sectionHeaderVisibilityProvider)
         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
         onStateChangeListener.accept("state change")
         verify(sectionHeaderVisibilityProvider).sectionHeadersVisible = eq(false)
     }
+
+    @Test
+    fun unseenFilterSuppressesSeenNotifWhileKeyguardShowing() {
+        whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+        // GIVEN: Keyguard is not showing, and a notification is present
+        keyguardRepository.setKeyguardShowing(false)
+        runKeyguardCoordinatorTest {
+            val fakeEntry = NotificationEntryBuilder().build()
+            collectionListener.onEntryAdded(fakeEntry)
+
+            // WHEN: The keyguard is now showing
+            keyguardRepository.setKeyguardShowing(true)
+            testScheduler.runCurrent()
+
+            // THEN: The notification is recognized as "seen" and is filtered out.
+            assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
+
+            // WHEN: The keyguard goes away
+            keyguardRepository.setKeyguardShowing(false)
+            testScheduler.runCurrent()
+
+            // THEN: The notification is shown regardless
+            assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
+        }
+    }
+
+    @Test
+    fun unseenFilterAllowsNewNotif() {
+        whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+        // GIVEN: Keyguard is showing, no notifications present
+        keyguardRepository.setKeyguardShowing(true)
+        runKeyguardCoordinatorTest {
+            // WHEN: A new notification is posted
+            val fakeEntry = NotificationEntryBuilder().build()
+            collectionListener.onEntryAdded(fakeEntry)
+
+            // THEN: The notification is recognized as "unseen" and is not filtered out.
+            assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
+        }
+    }
+
+    @Test
+    fun unseenFilterSeenGroupSummaryWithUnseenChild() {
+        whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+        // GIVEN: Keyguard is not showing, and a notification is present
+        keyguardRepository.setKeyguardShowing(false)
+        runKeyguardCoordinatorTest {
+            // WHEN: A new notification is posted
+            val fakeSummary = NotificationEntryBuilder().build()
+            val fakeChild = NotificationEntryBuilder()
+                    .setGroup(context, "group")
+                    .setGroupSummary(context, false)
+                    .build()
+            GroupEntryBuilder()
+                    .setSummary(fakeSummary)
+                    .addChild(fakeChild)
+                    .build()
+
+            collectionListener.onEntryAdded(fakeSummary)
+            collectionListener.onEntryAdded(fakeChild)
+
+            // WHEN: Keyguard is now showing, both notifications are marked as seen
+            keyguardRepository.setKeyguardShowing(true)
+            testScheduler.runCurrent()
+
+            // WHEN: The child notification is now unseen
+            collectionListener.onEntryUpdated(fakeChild)
+
+            // THEN: The summary is not filtered out, because the child is unseen
+            assertThat(unseenFilter.shouldFilterOut(fakeSummary, 0L)).isFalse()
+        }
+    }
+
+    @Test
+    fun unseenNotificationIsMarkedAsSeenWhenKeyguardGoesAway() {
+        whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+        // GIVEN: Keyguard is showing, unseen notification is present
+        keyguardRepository.setKeyguardShowing(true)
+        runKeyguardCoordinatorTest {
+            val fakeEntry = NotificationEntryBuilder().build()
+            collectionListener.onEntryAdded(fakeEntry)
+
+            // WHEN: Keyguard is no longer showing for 5 seconds
+            keyguardRepository.setKeyguardShowing(false)
+            testScheduler.runCurrent()
+            testScheduler.advanceTimeBy(5.seconds.inWholeMilliseconds)
+            testScheduler.runCurrent()
+
+            // WHEN: Keyguard is shown again
+            keyguardRepository.setKeyguardShowing(true)
+            testScheduler.runCurrent()
+
+            // THEN: The notification is now recognized as "seen" and is filtered out.
+            assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
+        }
+    }
+
+    @Test
+    fun unseenNotificationIsNotMarkedAsSeenIfTimeThresholdNotMet() {
+        whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+        // GIVEN: Keyguard is showing, unseen notification is present
+        keyguardRepository.setKeyguardShowing(true)
+        runKeyguardCoordinatorTest {
+            val fakeEntry = NotificationEntryBuilder().build()
+            collectionListener.onEntryAdded(fakeEntry)
+
+            // WHEN: Keyguard is no longer showing for <5 seconds
+            keyguardRepository.setKeyguardShowing(false)
+            testScheduler.runCurrent()
+            testScheduler.advanceTimeBy(1.seconds.inWholeMilliseconds)
+
+            // WHEN: Keyguard is shown again
+            keyguardRepository.setKeyguardShowing(true)
+            testScheduler.runCurrent()
+
+            // THEN: The notification is not recognized as "seen" and is not filtered out.
+            assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
+        }
+    }
+
+    private fun runKeyguardCoordinatorTest(
+        testBlock: suspend KeyguardCoordinatorTestScope.() -> Unit
+    ) {
+        val testScope = TestScope(UnconfinedTestDispatcher())
+        val keyguardCoordinator =
+            KeyguardCoordinator(
+                keyguardNotifVisibilityProvider,
+                keyguardRepository,
+                notifPipelineFlags,
+                testScope.backgroundScope,
+                sectionHeaderVisibilityProvider,
+                statusBarStateController,
+            )
+        keyguardCoordinator.attach(notifPipeline)
+        KeyguardCoordinatorTestScope(keyguardCoordinator, testScope).run {
+            testScheduler.advanceUntilIdle()
+            testScope.runTest(dispatchTimeoutMs = 1.seconds.inWholeMilliseconds) { testBlock() }
+        }
+    }
+
+    private inner class KeyguardCoordinatorTestScope(
+        private val keyguardCoordinator: KeyguardCoordinator,
+        private val scope: TestScope,
+    ) : CoroutineScope by scope {
+        val testScheduler: TestCoroutineScheduler
+            get() = scope.testScheduler
+
+        val onStateChangeListener: Consumer<String> =
+            withArgCaptor {
+                verify(keyguardNotifVisibilityProvider).addOnStateChangedListener(capture())
+            }
+
+        val unseenFilter: NotifFilter
+            get() = keyguardCoordinator.unseenNotifFilter
+
+        // TODO(254647461): Remove lazy once Flags.FILTER_UNSEEN_NOTIFS_ON_KEYGUARD is enabled and
+        //  removed
+        val collectionListener: NotifCollectionListener by lazy {
+            withArgCaptor { verify(notifPipeline).addCollectionListener(capture()) }
+        }
+    }
 }
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 b4a5f5c..e488f39 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
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertFalse;
 
 import static org.junit.Assert.assertTrue;
@@ -38,6 +40,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeStateEvents;
 import com.android.systemui.shade.ShadeStateEvents.ShadeStateEventsListener;
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -73,6 +76,7 @@
     @Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener;
     @Mock private HeadsUpManager mHeadsUpManager;
     @Mock private ShadeStateEvents mShadeStateEvents;
+    @Mock private VisibilityLocationProvider mVisibilityLocationProvider;
     @Mock private VisualStabilityProvider mVisualStabilityProvider;
 
     @Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
@@ -100,6 +104,7 @@
                 mHeadsUpManager,
                 mShadeStateEvents,
                 mStatusBarStateController,
+                mVisibilityLocationProvider,
                 mVisualStabilityProvider,
                 mWakefulnessLifecycle);
 
@@ -355,6 +360,38 @@
     }
 
     @Test
+    public void testMovingVisibleHeadsUpNotAllowed() {
+        // GIVEN stability enforcing conditions
+        setPanelExpanded(true);
+        setSleepy(false);
+
+        // WHEN a notification is alerting and visible
+        when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true);
+        when(mVisibilityLocationProvider.isInVisibleLocation(any(NotificationEntry.class)))
+                .thenReturn(true);
+
+        // VERIFY the notification cannot be reordered
+        assertThat(mNotifStabilityManager.isEntryReorderingAllowed(mEntry)).isFalse();
+        assertThat(mNotifStabilityManager.isSectionChangeAllowed(mEntry)).isFalse();
+    }
+
+    @Test
+    public void testMovingInvisibleHeadsUpAllowed() {
+        // GIVEN stability enforcing conditions
+        setPanelExpanded(true);
+        setSleepy(false);
+
+        // WHEN a notification is alerting but not visible
+        when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true);
+        when(mVisibilityLocationProvider.isInVisibleLocation(any(NotificationEntry.class)))
+                .thenReturn(false);
+
+        // VERIFY the notification can be reordered
+        assertThat(mNotifStabilityManager.isEntryReorderingAllowed(mEntry)).isTrue();
+        assertThat(mNotifStabilityManager.isSectionChangeAllowed(mEntry)).isTrue();
+    }
+
+    @Test
     public void testNeverSuppressedChanges_noInvalidationCalled() {
         // GIVEN no notifications are currently being suppressed from grouping nor being sorted
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 90061b0..026c82e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -61,6 +61,7 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
@@ -122,6 +123,7 @@
     @Mock private UiEventLogger mUiEventLogger;
     @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
     @Mock private ShadeController mShadeController;
     @Mock private InteractionJankMonitor mJankMonitor;
     @Mock private StackStateLogger mStackLogger;
@@ -173,6 +175,7 @@
                 mShadeTransitionController,
                 mUiEventLogger,
                 mRemoteInputManager,
+                mVisibilityLocationProviderDelegator,
                 mShadeController,
                 mJankMonitor,
                 mStackLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index 57fb976..bf31eb28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -41,6 +41,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -60,6 +61,8 @@
 
 import java.util.Optional;
 
+import dagger.Lazy;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
@@ -84,6 +87,7 @@
     @Mock private Vibrator mVibrator;
     @Mock private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
     @Mock private SystemBarAttributesListener mSystemBarAttributesListener;
+    @Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
 
     CentralSurfacesCommandQueueCallbacks mSbcqCallbacks;
 
@@ -115,7 +119,8 @@
                 Optional.of(mVibrator),
                 new DisableFlagsLogger(),
                 DEFAULT_DISPLAY,
-                mSystemBarAttributesListener);
+                mSystemBarAttributesListener,
+                mCameraLauncherLazy);
 
         when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
         when(mRemoteInputQuickSettingsDisabler.adjustDisableFlags(anyInt()))
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 5ad1431..41912f5 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
@@ -112,6 +112,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.shade.CameraLauncher;
 import com.android.systemui.shade.NotificationPanelView;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.shade.NotificationShadeWindowView;
@@ -288,6 +289,8 @@
     @Mock private InteractionJankMonitor mJankMonitor;
     @Mock private DeviceStateManager mDeviceStateManager;
     @Mock private WiredChargingRippleController mWiredChargingRippleController;
+    @Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
+    @Mock private CameraLauncher mCameraLauncher;
     /**
      * The process of registering/unregistering a predictive back callback requires a
      * ViewRootImpl, which is present IRL, but may be missing during a Mockito unit test.
@@ -380,6 +383,7 @@
 
         when(mLockscreenWallpaperLazy.get()).thenReturn(mLockscreenWallpaper);
         when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController);
+        when(mCameraLauncherLazy.get()).thenReturn(mCameraLauncher);
 
         when(mStatusBarComponentFactory.create()).thenReturn(mCentralSurfacesComponent);
         when(mCentralSurfacesComponent.getNotificationShadeWindowViewController()).thenReturn(
@@ -481,7 +485,9 @@
                 mActivityLaunchAnimator,
                 mJankMonitor,
                 mDeviceStateManager,
-                mWiredChargingRippleController, mDreamManager) {
+                mWiredChargingRippleController,
+                mDreamManager,
+                mCameraLauncherLazy) {
             @Override
             protected ViewRootImpl getViewRootImpl() {
                 return mViewRootImpl;
@@ -893,7 +899,7 @@
         mCentralSurfaces.showKeyguardImpl();
 
         // Starting a pulse should change the scrim controller to the pulsing state
-        when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(true);
+        when(mCameraLauncher.isLaunchingAffordance()).thenReturn(true);
         mCentralSurfaces.updateScrimController();
         verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any());
     }
@@ -929,7 +935,7 @@
         mCentralSurfaces.showKeyguardImpl();
 
         // Starting a pulse should change the scrim controller to the pulsing state
-        when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(false);
+        when(mCameraLauncher.isLaunchingAffordance()).thenReturn(false);
         mCentralSurfaces.updateScrimController();
         verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
index fee3ccb..038af8f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
@@ -14,23 +14,37 @@
 
 package com.android.systemui.statusbar.phone
 
-import androidx.test.filters.SmallTest
+import android.content.res.Configuration
+import android.content.res.Configuration.SCREENLAYOUT_LAYOUTDIR_LTR
+import android.content.res.Configuration.SCREENLAYOUT_LAYOUTDIR_RTL
+import android.content.res.Configuration.UI_MODE_NIGHT_NO
+import android.content.res.Configuration.UI_MODE_NIGHT_YES
+import android.content.res.Configuration.UI_MODE_TYPE_CAR
+import android.os.LocaleList
 import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
+import java.util.Locale
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
 class ConfigurationControllerImplTest : SysuiTestCase() {
 
-    private val mConfigurationController =
-            com.android.systemui.statusbar.phone.ConfigurationControllerImpl(mContext)
+    private lateinit var mConfigurationController: ConfigurationControllerImpl
+
+    @Before
+    fun setUp() {
+        mConfigurationController = ConfigurationControllerImpl(mContext)
+    }
 
     @Test
     fun testThemeChange() {
@@ -57,4 +71,303 @@
         verify(listener).onThemeChanged()
         verify(listener2, never()).onThemeChanged()
     }
+
+    @Test
+    fun configChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.densityDpi = 12
+        config.smallestScreenWidthDp = 240
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the config is updated
+        config.densityDpi = 20
+        config.smallestScreenWidthDp = 300
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.changedConfig?.densityDpi).isEqualTo(20)
+        assertThat(listener.changedConfig?.smallestScreenWidthDp).isEqualTo(300)
+    }
+
+    @Test
+    fun densityChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.densityDpi = 12
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the density is updated
+        config.densityDpi = 20
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.densityOrFontScaleChanged).isTrue()
+    }
+
+    @Test
+    fun fontChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.fontScale = 1.5f
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the font is updated
+        config.fontScale = 1.4f
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.densityOrFontScaleChanged).isTrue()
+    }
+
+    @Test
+    fun isCarAndUiModeChanged_densityListenerNotified() {
+        val config = mContext.resources.configuration
+        config.uiMode = UI_MODE_TYPE_CAR or UI_MODE_NIGHT_YES
+        // Re-create the controller since we calculate car mode on creation
+        mConfigurationController = ConfigurationControllerImpl(mContext)
+
+        val listener = createAndAddListener()
+
+        // WHEN the ui mode is updated
+        config.uiMode = UI_MODE_TYPE_CAR or UI_MODE_NIGHT_NO
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.densityOrFontScaleChanged).isTrue()
+    }
+
+    @Test
+    fun isNotCarAndUiModeChanged_densityListenerNotNotified() {
+        val config = mContext.resources.configuration
+        config.uiMode = UI_MODE_NIGHT_YES
+        // Re-create the controller since we calculate car mode on creation
+        mConfigurationController = ConfigurationControllerImpl(mContext)
+
+        val listener = createAndAddListener()
+
+        // WHEN the ui mode is updated
+        config.uiMode = UI_MODE_NIGHT_NO
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is not notified because it's not car mode
+        assertThat(listener.densityOrFontScaleChanged).isFalse()
+    }
+
+    @Test
+    fun smallestScreenWidthChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.smallestScreenWidthDp = 240
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the width is updated
+        config.smallestScreenWidthDp = 300
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.smallestScreenWidthChanged).isTrue()
+    }
+
+    @Test
+    fun maxBoundsChange_newConfigObject_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.windowConfiguration.setMaxBounds(0, 0, 200, 200)
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN a new configuration object with new bounds is sent
+        val newConfig = Configuration()
+        newConfig.windowConfiguration.setMaxBounds(0, 0, 100, 100)
+        mConfigurationController.onConfigurationChanged(newConfig)
+
+        // THEN the listener is notified
+        assertThat(listener.maxBoundsChanged).isTrue()
+    }
+
+    // Regression test for b/245799099
+    @Test
+    fun maxBoundsChange_sameObject_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.windowConfiguration.setMaxBounds(0, 0, 200, 200)
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the existing config is updated with new bounds
+        config.windowConfiguration.setMaxBounds(0, 0, 100, 100)
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.maxBoundsChanged).isTrue()
+    }
+
+
+    @Test
+    fun localeListChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.locales = LocaleList(Locale.CANADA, Locale.GERMANY)
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the locales are updated
+        config.locales = LocaleList(Locale.FRANCE, Locale.JAPAN, Locale.CHINESE)
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.localeListChanged).isTrue()
+    }
+
+    @Test
+    fun uiModeChanged_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.uiMode = UI_MODE_NIGHT_YES
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the ui mode is updated
+        config.uiMode = UI_MODE_NIGHT_NO
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.uiModeChanged).isTrue()
+    }
+
+    @Test
+    fun layoutDirectionUpdated_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.screenLayout = SCREENLAYOUT_LAYOUTDIR_LTR
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the layout is updated
+        config.screenLayout = SCREENLAYOUT_LAYOUTDIR_RTL
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.layoutDirectionChanged).isTrue()
+    }
+
+    @Test
+    fun assetPathsUpdated_listenerNotified() {
+        val config = mContext.resources.configuration
+        config.assetsSeq = 45
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN the assets sequence is updated
+        config.assetsSeq = 46
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified
+        assertThat(listener.themeChanged).isTrue()
+    }
+
+    @Test
+    fun multipleUpdates_listenerNotifiedOfAll() {
+        val config = mContext.resources.configuration
+        config.densityDpi = 14
+        config.windowConfiguration.setMaxBounds(0, 0, 2, 2)
+        config.uiMode = UI_MODE_NIGHT_YES
+        mConfigurationController.onConfigurationChanged(config)
+
+        val listener = createAndAddListener()
+
+        // WHEN multiple fields are updated
+        config.densityDpi = 20
+        config.windowConfiguration.setMaxBounds(0, 0, 3, 3)
+        config.uiMode = UI_MODE_NIGHT_NO
+        mConfigurationController.onConfigurationChanged(config)
+
+        // THEN the listener is notified of all of them
+        assertThat(listener.densityOrFontScaleChanged).isTrue()
+        assertThat(listener.maxBoundsChanged).isTrue()
+        assertThat(listener.uiModeChanged).isTrue()
+    }
+
+    @Test
+    fun equivalentConfigObject_listenerNotNotified() {
+        val config = mContext.resources.configuration
+        val listener = createAndAddListener()
+
+        // WHEN we update with the new object that has all the same fields
+        mConfigurationController.onConfigurationChanged(Configuration(config))
+
+        listener.assertNoMethodsCalled()
+    }
+
+    private fun createAndAddListener(): TestListener {
+        val listener = TestListener()
+        mConfigurationController.addCallback(listener)
+        // Adding a listener can trigger some callbacks, so we want to reset the values right
+        // after the listener is added
+        listener.reset()
+        return listener
+    }
+
+    private class TestListener : ConfigurationListener {
+        var changedConfig: Configuration? = null
+        var densityOrFontScaleChanged = false
+        var smallestScreenWidthChanged = false
+        var maxBoundsChanged = false
+        var uiModeChanged = false
+        var themeChanged = false
+        var localeListChanged = false
+        var layoutDirectionChanged = false
+
+        override fun onConfigChanged(newConfig: Configuration?) {
+            changedConfig = newConfig
+        }
+        override fun onDensityOrFontScaleChanged() {
+            densityOrFontScaleChanged = true
+        }
+        override fun onSmallestScreenWidthChanged() {
+            smallestScreenWidthChanged = true
+        }
+        override fun onMaxBoundsChanged() {
+            maxBoundsChanged = true
+        }
+        override fun onUiModeChanged() {
+            uiModeChanged = true
+        }
+        override fun onThemeChanged() {
+            themeChanged = true
+        }
+        override fun onLocaleListChanged() {
+            localeListChanged = true
+        }
+        override fun onLayoutDirectionChanged(isLayoutRtl: Boolean) {
+            layoutDirectionChanged = true
+        }
+
+        fun assertNoMethodsCalled() {
+            assertThat(densityOrFontScaleChanged).isFalse()
+            assertThat(smallestScreenWidthChanged).isFalse()
+            assertThat(maxBoundsChanged).isFalse()
+            assertThat(uiModeChanged).isFalse()
+            assertThat(themeChanged).isFalse()
+            assertThat(localeListChanged).isFalse()
+            assertThat(layoutDirectionChanged).isFalse()
+        }
+
+        fun reset() {
+            changedConfig = null
+            densityOrFontScaleChanged = false
+            smallestScreenWidthChanged = false
+            maxBoundsChanged = false
+            uiModeChanged = false
+            themeChanged = false
+            localeListChanged = false
+            layoutDirectionChanged = false
+        }
+    }
 }
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 df48e1d..de71e2c 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
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.statusbar.phone.ScrimController.KEYGUARD_SCRIM_ALPHA;
 import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE;
 import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
@@ -59,7 +58,6 @@
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.statusbar.policy.FakeConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -119,7 +117,6 @@
     // TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
     //   event-dispatch-on-registration pattern caused some of these unit tests to fail.)
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    @Mock private KeyguardViewMediator mKeyguardViewMediator;
 
     private static class AnimatorListener implements Animator.AnimatorListener {
         private int mNumStarts;
@@ -233,8 +230,7 @@
                 mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager,
-                mKeyguardViewMediator);
+                mStatusBarKeyguardViewManager);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -243,8 +239,6 @@
         mScrimController.setWallpaperSupportsAmbientMode(false);
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         finishAnimationsImmediately();
-
-        mScrimController.setLaunchingAffordanceWithPreview(false);
     }
 
     @After
@@ -858,8 +852,7 @@
                 mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager,
-                mKeyguardViewMediator);
+                mStatusBarKeyguardViewManager);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1437,6 +1430,17 @@
     }
 
     @Test
+    public void behindTint_inKeyguardState_bouncerNotActive_usesKeyguardBehindTint() {
+        when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false);
+        mScrimController.setClipsQsScrim(false);
+
+        mScrimController.transitionTo(ScrimState.KEYGUARD);
+        finishAnimationsImmediately();
+        assertThat(mScrimBehind.getTint())
+                .isEqualTo(ScrimState.KEYGUARD.getBehindTint());
+    }
+
+    @Test
     public void testNotificationTransparency_followsTransitionToFullShade() {
         mScrimController.transitionTo(SHADE_LOCKED);
         mScrimController.setRawPanelExpansionFraction(1.0f);
@@ -1627,30 +1631,6 @@
         assertScrimAlpha(mScrimBehind, 0);
     }
 
-    @Test
-    public void keyguardAlpha_whenUnlockedForOcclusion_ifPlayingOcclusionAnimation() {
-        mScrimController.transitionTo(ScrimState.KEYGUARD);
-
-        when(mKeyguardViewMediator.isOccludeAnimationPlaying()).thenReturn(true);
-
-        mScrimController.transitionTo(ScrimState.UNLOCKED);
-        finishAnimationsImmediately();
-
-        assertScrimAlpha(mNotificationsScrim, (int) (KEYGUARD_SCRIM_ALPHA * 255f));
-    }
-
-    @Test
-    public void keyguardAlpha_whenUnlockedForLaunch_ifLaunchingAffordance() {
-        mScrimController.transitionTo(ScrimState.KEYGUARD);
-        when(mKeyguardViewMediator.isOccludeAnimationPlaying()).thenReturn(true);
-        mScrimController.setLaunchingAffordanceWithPreview(true);
-
-        mScrimController.transitionTo(ScrimState.UNLOCKED);
-        finishAnimationsImmediately();
-
-        assertScrimAlpha(mNotificationsScrim, (int) (KEYGUARD_SCRIM_ALPHA * 255f));
-    }
-
     private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
         mScrimController.setRawPanelExpansionFraction(expansion);
         finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index e86676b..1759fb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -19,9 +19,9 @@
 import android.content.Context
 import android.content.res.Configuration
 import android.graphics.Rect
-import android.test.suitebuilder.annotation.SmallTest
 import android.view.Display
 import android.view.DisplayCutout
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.policy.ConfigurationController
@@ -463,16 +463,10 @@
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
             mock(DumpManager::class.java))
 
-        givenDisplay(
-            screenBounds = Rect(0, 0, 1080, 2160),
-            displayUniqueId = "1"
-        )
+        configuration.windowConfiguration.maxBounds = Rect(0, 0, 1080, 2160)
         val firstDisplayInsets = provider.getStatusBarContentAreaForRotation(ROTATION_NONE)
-        givenDisplay(
-            screenBounds = Rect(0, 0, 800, 600),
-            displayUniqueId = "2"
-        )
-        configurationController.onConfigurationChanged(configuration)
+
+        configuration.windowConfiguration.maxBounds = Rect(0, 0, 800, 600)
 
         // WHEN: get insets on the second display
         val secondDisplayInsets = provider.getStatusBarContentAreaForRotation(ROTATION_NONE)
@@ -487,23 +481,15 @@
         // get insets and switch back
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
             mock(DumpManager::class.java))
-        givenDisplay(
-            screenBounds = Rect(0, 0, 1080, 2160),
-            displayUniqueId = "1"
-        )
+
+        configuration.windowConfiguration.maxBounds = Rect(0, 0, 1080, 2160)
         val firstDisplayInsetsFirstCall = provider
             .getStatusBarContentAreaForRotation(ROTATION_NONE)
-        givenDisplay(
-            screenBounds = Rect(0, 0, 800, 600),
-            displayUniqueId = "2"
-        )
-        configurationController.onConfigurationChanged(configuration)
+
+        configuration.windowConfiguration.maxBounds = Rect(0, 0, 800, 600)
         provider.getStatusBarContentAreaForRotation(ROTATION_NONE)
-        givenDisplay(
-            screenBounds = Rect(0, 0, 1080, 2160),
-            displayUniqueId = "1"
-        )
-        configurationController.onConfigurationChanged(configuration)
+
+        configuration.windowConfiguration.maxBounds = Rect(0, 0, 1080, 2160)
 
         // WHEN: get insets on the first display again
         val firstDisplayInsetsSecondCall = provider
@@ -513,9 +499,70 @@
         assertThat(firstDisplayInsetsFirstCall).isEqualTo(firstDisplayInsetsSecondCall)
     }
 
-    private fun givenDisplay(screenBounds: Rect, displayUniqueId: String) {
-        `when`(display.uniqueId).thenReturn(displayUniqueId)
-        configuration.windowConfiguration.maxBounds = screenBounds
+    // Regression test for b/245799099
+    @Test
+    fun onMaxBoundsChanged_listenerNotified() {
+        // Start out with an existing configuration with bounds
+        configuration.windowConfiguration.setMaxBounds(0, 0, 100, 100)
+        configurationController.onConfigurationChanged(configuration)
+        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
+                mock(DumpManager::class.java))
+        val listener = object : StatusBarContentInsetsChangedListener {
+            var triggered = false
+
+            override fun onStatusBarContentInsetsChanged() {
+                triggered = true
+            }
+        }
+        provider.addCallback(listener)
+
+        // WHEN the config is updated with new bounds
+        configuration.windowConfiguration.setMaxBounds(0, 0, 456, 789)
+        configurationController.onConfigurationChanged(configuration)
+
+        // THEN the listener is notified
+        assertThat(listener.triggered).isTrue()
+    }
+
+    @Test
+    fun onDensityOrFontScaleChanged_listenerNotified() {
+        configuration.densityDpi = 12
+        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
+                mock(DumpManager::class.java))
+        val listener = object : StatusBarContentInsetsChangedListener {
+            var triggered = false
+
+            override fun onStatusBarContentInsetsChanged() {
+                triggered = true
+            }
+        }
+        provider.addCallback(listener)
+
+        // WHEN the config is updated
+        configuration.densityDpi = 20
+        configurationController.onConfigurationChanged(configuration)
+
+        // THEN the listener is notified
+        assertThat(listener.triggered).isTrue()
+    }
+
+    @Test
+    fun onThemeChanged_listenerNotified() {
+        val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
+                mock(DumpManager::class.java))
+        val listener = object : StatusBarContentInsetsChangedListener {
+            var triggered = false
+
+            override fun onStatusBarContentInsetsChanged() {
+                triggered = true
+            }
+        }
+        provider.addCallback(listener)
+
+        configurationController.notifyThemeChanged()
+
+        // THEN the listener is notified
+        assertThat(listener.triggered).isTrue()
     }
 
     private fun assertRects(
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 49c3a21..9f70565 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
@@ -222,9 +222,16 @@
     }
 
     @Test
-    public void onPanelExpansionChanged_neverHidesScrimmedBouncer() {
+    public void onPanelExpansionChanged_neverHidesFullscreenBouncer() {
         when(mPrimaryBouncer.isShowing()).thenReturn(true);
-        when(mPrimaryBouncer.isScrimmed()).thenReturn(true);
+        when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
+                KeyguardSecurityModel.SecurityMode.SimPuk);
+        mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
+        verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
+
+        reset(mPrimaryBouncer);
+        when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
+                KeyguardSecurityModel.SecurityMode.SimPin);
         mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
         verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
     }
@@ -271,13 +278,6 @@
     }
 
     @Test
-    public void onPanelExpansionChanged_neverTranslatesBouncerWhenOccluded() {
-        mStatusBarKeyguardViewManager.setOccluded(true /* occluded */, false /* animate */);
-        mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
-        verify(mPrimaryBouncer, never()).setExpansion(eq(0.5f));
-    }
-
-    @Test
     public void onPanelExpansionChanged_neverTranslatesBouncerWhenWakeAndUnlock() {
         when(mBiometricUnlockController.getMode())
                 .thenReturn(BiometricUnlockController.MODE_WAKE_AND_UNLOCK);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt
index 6d8d902..a052008 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt
@@ -16,31 +16,59 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.util
 
+import android.telephony.TelephonyDisplayInfo
 import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.settingslib.mobile.MobileMappings.Config
 import com.android.settingslib.mobile.TelephonyIcons
 
 class FakeMobileMappingsProxy : MobileMappingsProxy {
+    // The old [NetworkControllerDataTest] infra requires us to be able to use the real
+    // impl sometimes
+    var useRealImpl = false
+
+    private var realImpl = MobileMappingsProxyImpl()
     private var iconMap = mapOf<String, MobileIconGroup>()
     private var defaultIcons = TelephonyIcons.THREE_G
 
     fun setIconMap(map: Map<String, MobileIconGroup>) {
         iconMap = map
     }
-    override fun mapIconSets(config: Config): Map<String, MobileIconGroup> = iconMap
+    override fun mapIconSets(config: Config): Map<String, MobileIconGroup> {
+        if (useRealImpl) {
+            return realImpl.mapIconSets(config)
+        }
+        return iconMap
+    }
     fun getIconMap() = iconMap
 
     fun setDefaultIcons(group: MobileIconGroup) {
         defaultIcons = group
     }
-    override fun getDefaultIcons(config: Config): MobileIconGroup = defaultIcons
+    override fun getDefaultIcons(config: Config): MobileIconGroup {
+        if (useRealImpl) {
+            return realImpl.getDefaultIcons(config)
+        }
+        return defaultIcons
+    }
+
+    /** This is only used in the old pipeline, use the real impl always */
+    override fun getIconKey(displayInfo: TelephonyDisplayInfo): String {
+        return realImpl.getIconKey(displayInfo)
+    }
+
     fun getDefaultIcons(): MobileIconGroup = defaultIcons
 
     override fun toIconKey(networkType: Int): String {
+        if (useRealImpl) {
+            return realImpl.toIconKeyOverride(networkType)
+        }
         return networkType.toString()
     }
 
     override fun toIconKeyOverride(networkType: Int): String {
+        if (useRealImpl) {
+            return realImpl.toIconKeyOverride(networkType)
+        }
         return toIconKey(networkType) + "_override"
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
index f304647..0a3da0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
@@ -237,7 +237,7 @@
     fun refresh() {
         underTest.refresh()
 
-        verify(controller).refreshUsers(UserHandle.USER_NULL)
+        verify(controller).refreshUsers()
     }
 
     private fun createUserRecord(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index 43d0fe9..1eee08c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -221,4 +221,33 @@
 
         Assert.assertFalse(mBatteryController.isChargingSourceDock());
     }
+
+    @Test
+    public void batteryStateChanged_healthNotOverheated_outputsFalse() {
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intent.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_GOOD);
+
+        mBatteryController.onReceive(getContext(), intent);
+
+        Assert.assertFalse(mBatteryController.isOverheated());
+    }
+
+    @Test
+    public void batteryStateChanged_healthOverheated_outputsTrue() {
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intent.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT);
+
+        mBatteryController.onReceive(getContext(), intent);
+
+        Assert.assertTrue(mBatteryController.isOverheated());
+    }
+
+    @Test
+    public void batteryStateChanged_noHealthGiven_outputsFalse() {
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+
+        mBatteryController.onReceive(getContext(), intent);
+
+        Assert.assertFalse(mBatteryController.isOverheated());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index d0391ac..833cabb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.bluetooth.BluetoothLogger;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -56,6 +57,7 @@
 @SmallTest
 public class BluetoothControllerImplTest extends SysuiTestCase {
 
+    private UserTracker mUserTracker;
     private LocalBluetoothManager mMockBluetoothManager;
     private CachedBluetoothDeviceManager mMockDeviceManager;
     private LocalBluetoothAdapter mMockAdapter;
@@ -70,6 +72,7 @@
         mTestableLooper = TestableLooper.get(this);
         mMockBluetoothManager = mDependency.injectMockDependency(LocalBluetoothManager.class);
         mDevices = new ArrayList<>();
+        mUserTracker = mock(UserTracker.class);
         mMockDeviceManager = mock(CachedBluetoothDeviceManager.class);
         when(mMockDeviceManager.getCachedDevicesCopy()).thenReturn(mDevices);
         when(mMockBluetoothManager.getCachedDeviceManager()).thenReturn(mMockDeviceManager);
@@ -81,6 +84,7 @@
         mMockDumpManager = mock(DumpManager.class);
 
         mBluetoothControllerImpl = new BluetoothControllerImpl(mContext,
+                mUserTracker,
                 mMockDumpManager,
                 mock(BluetoothLogger.class),
                 mTestableLooper.getLooper(),
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 26df03f..dc08aba 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
@@ -41,6 +41,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -61,6 +62,8 @@
 public class HotspotControllerImplTest extends SysuiTestCase {
 
     @Mock
+    private UserTracker mUserTracker;
+    @Mock
     private DumpManager mDumpManager;
     @Mock
     private TetheringManager mTetheringManager;
@@ -104,7 +107,8 @@
 
         Handler handler = new Handler(mLooper.getLooper());
 
-        mController = new HotspotControllerImpl(mContext, handler, handler, mDumpManager);
+        mController = new HotspotControllerImpl(mContext, mUserTracker, handler, handler,
+                mDumpManager);
         verify(mTetheringManager)
                 .registerTetheringEventCallback(any(), mTetheringCallbackCaptor.capture());
     }
@@ -191,7 +195,7 @@
         Handler handler = new Handler(mLooper.getLooper());
 
         HotspotController controller =
-                new HotspotControllerImpl(mContext, handler, handler, mDumpManager);
+                new HotspotControllerImpl(mContext, mUserTracker, handler, handler, mDumpManager);
 
         verifyNoMoreInteractions(mTetheringManager);
         assertFalse(controller.isHotspotSupported());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index d44cdb2..15235b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -50,6 +50,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -72,10 +73,12 @@
     private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
     private final IKeyChainService.Stub mKeyChainService = mock(IKeyChainService.Stub.class);
     private final UserManager mUserManager = mock(UserManager.class);
+    private final UserTracker mUserTracker = mock(UserTracker.class);
     private final BroadcastDispatcher mBroadcastDispatcher = mock(BroadcastDispatcher.class);
     private final Handler mHandler = mock(Handler.class);
     private SecurityControllerImpl mSecurityController;
     private ConnectivityManager mConnectivityManager = mock(ConnectivityManager.class);
+    private FakeExecutor mMainExecutor;
     private FakeExecutor mBgExecutor;
     private BroadcastReceiver mBroadcastReceiver;
 
@@ -102,11 +105,14 @@
         ArgumentCaptor<BroadcastReceiver> brCaptor =
                 ArgumentCaptor.forClass(BroadcastReceiver.class);
 
+        mMainExecutor = new FakeExecutor(new FakeSystemClock());
         mBgExecutor = new FakeExecutor(new FakeSystemClock());
         mSecurityController = new SecurityControllerImpl(
                 mContext,
+                mUserTracker,
                 mHandler,
                 mBroadcastDispatcher,
+                mMainExecutor,
                 mBgExecutor,
                 Mockito.mock(DumpManager.class));
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
deleted file mode 100644
index 169f4fb..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.policy
-
-import android.app.IActivityManager
-import android.app.NotificationManager
-import android.app.admin.DevicePolicyManager
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.DialogInterface
-import android.content.Intent
-import android.content.pm.UserInfo
-import android.graphics.Bitmap
-import android.hardware.face.FaceManager
-import android.hardware.fingerprint.FingerprintManager
-import android.os.Handler
-import android.os.UserHandle
-import android.os.UserManager
-import android.provider.Settings
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.ThreadedRenderer
-import androidx.test.filters.SmallTest
-import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.internal.util.LatencyTracker
-import com.android.internal.util.UserIcons
-import com.android.systemui.GuestResetOrExitSessionReceiver
-import com.android.systemui.GuestResumeSessionReceiver
-import com.android.systemui.GuestSessionNotification
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.DialogCuj
-import com.android.systemui.animation.DialogLaunchAnimator
-import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.broadcast.BroadcastSender
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.qs.QSUserSwitcherEvent
-import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.settings.UserTracker
-import com.android.systemui.shade.NotificationShadeWindowView
-import com.android.systemui.telephony.TelephonyListenerManager
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.user.legacyhelper.data.LegacyUserDataHelper
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.kotlinArgumentCaptor
-import com.android.systemui.util.mockito.nullable
-import com.android.systemui.util.settings.GlobalSettings
-import com.android.systemui.util.settings.SecureSettings
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.eq
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class UserSwitcherControllerOldImplTest : SysuiTestCase() {
-    @Mock private lateinit var keyguardStateController: KeyguardStateController
-    @Mock private lateinit var activityManager: IActivityManager
-    @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
-    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
-    @Mock private lateinit var handler: Handler
-    @Mock private lateinit var userTracker: UserTracker
-    @Mock private lateinit var userManager: UserManager
-    @Mock private lateinit var activityStarter: ActivityStarter
-    @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
-    @Mock private lateinit var broadcastSender: BroadcastSender
-    @Mock private lateinit var telephonyListenerManager: TelephonyListenerManager
-    @Mock private lateinit var secureSettings: SecureSettings
-    @Mock private lateinit var falsingManager: FalsingManager
-    @Mock private lateinit var dumpManager: DumpManager
-    @Mock private lateinit var interactionJankMonitor: InteractionJankMonitor
-    @Mock private lateinit var latencyTracker: LatencyTracker
-    @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower
-    @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView
-    @Mock private lateinit var threadedRenderer: ThreadedRenderer
-    @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
-    @Mock private lateinit var globalSettings: GlobalSettings
-    @Mock private lateinit var guestSessionNotification: GuestSessionNotification
-    @Mock private lateinit var guestResetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
-    private lateinit var resetSessionDialogFactory:
-                            GuestResumeSessionReceiver.ResetSessionDialog.Factory
-    private lateinit var guestResumeSessionReceiver: GuestResumeSessionReceiver
-    private lateinit var testableLooper: TestableLooper
-    private lateinit var bgExecutor: FakeExecutor
-    private lateinit var longRunningExecutor: FakeExecutor
-    private lateinit var uiExecutor: FakeExecutor
-    private lateinit var uiEventLogger: UiEventLoggerFake
-    private lateinit var userSwitcherController: UserSwitcherControllerOldImpl
-    private lateinit var picture: Bitmap
-    private val ownerId = UserHandle.USER_SYSTEM
-    private val ownerInfo = UserInfo(ownerId, "Owner", null,
-            UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL or UserInfo.FLAG_INITIALIZED or
-                    UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_ADMIN,
-            UserManager.USER_TYPE_FULL_SYSTEM)
-    private val guestId = 1234
-    private val guestInfo = UserInfo(guestId, "Guest", null,
-            UserInfo.FLAG_FULL or UserInfo.FLAG_GUEST, UserManager.USER_TYPE_FULL_GUEST)
-    private val secondaryUser =
-            UserInfo(10, "Secondary", null, 0, UserManager.USER_TYPE_FULL_SECONDARY)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        testableLooper = TestableLooper.get(this)
-        bgExecutor = FakeExecutor(FakeSystemClock())
-        longRunningExecutor = FakeExecutor(FakeSystemClock())
-        uiExecutor = FakeExecutor(FakeSystemClock())
-        uiEventLogger = UiEventLoggerFake()
-
-        mContext.orCreateTestableResources.addOverride(
-                com.android.internal.R.bool.config_guestUserAutoCreated, false)
-
-        mContext.addMockSystemService(Context.FACE_SERVICE, mock(FaceManager::class.java))
-        mContext.addMockSystemService(Context.NOTIFICATION_SERVICE,
-                mock(NotificationManager::class.java))
-        mContext.addMockSystemService(Context.FINGERPRINT_SERVICE,
-                mock(FingerprintManager::class.java))
-
-        resetSessionDialogFactory = object : GuestResumeSessionReceiver.ResetSessionDialog.Factory {
-                override fun create(userId: Int): GuestResumeSessionReceiver.ResetSessionDialog {
-                    return GuestResumeSessionReceiver.ResetSessionDialog(
-                                mContext,
-                                mock(UserSwitcherController::class.java),
-                                uiEventLogger,
-                                userId
-                            )
-                }
-            }
-
-        guestResumeSessionReceiver = GuestResumeSessionReceiver(userTracker,
-                                        secureSettings,
-                                        broadcastDispatcher,
-                                        guestSessionNotification,
-                                        resetSessionDialogFactory)
-
-        `when`(userManager.canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_SECONDARY)))
-                .thenReturn(true)
-        `when`(notificationShadeWindowView.context).thenReturn(context)
-
-        // Since userSwitcherController involves InteractionJankMonitor.
-        // Let's fulfill the dependencies.
-        val mockedContext = mock(Context::class.java)
-        doReturn(mockedContext).`when`(notificationShadeWindowView).context
-        doReturn(true).`when`(notificationShadeWindowView).isAttachedToWindow
-        doNothing().`when`(threadedRenderer).addObserver(any())
-        doNothing().`when`(threadedRenderer).removeObserver(any())
-        doReturn(threadedRenderer).`when`(notificationShadeWindowView).threadedRenderer
-
-        picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
-
-        // Create defaults for the current user
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.ADD_USERS_WHEN_LOCKED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(1)
-
-        setupController()
-    }
-
-    private fun setupController() {
-        userSwitcherController =
-            UserSwitcherControllerOldImpl(
-                mContext,
-                activityManager,
-                userManager,
-                userTracker,
-                keyguardStateController,
-                deviceProvisionedController,
-                devicePolicyManager,
-                handler,
-                activityStarter,
-                broadcastDispatcher,
-                broadcastSender,
-                uiEventLogger,
-                falsingManager,
-                telephonyListenerManager,
-                secureSettings,
-                globalSettings,
-                bgExecutor,
-                longRunningExecutor,
-                uiExecutor,
-                interactionJankMonitor,
-                latencyTracker,
-                dumpManager,
-                dialogLaunchAnimator,
-                guestResumeSessionReceiver,
-                guestResetOrExitSessionReceiver
-            )
-        userSwitcherController.init(notificationShadeWindowView)
-    }
-
-    @Test
-    fun testSwitchUser_parentDialogDismissed() {
-        val otherUserRecord = UserRecord(
-            secondaryUser,
-            picture,
-            false /* guest */,
-            false /* current */,
-            false /* isAddUser */,
-            false /* isRestricted */,
-            true /* isSwitchToEnabled */,
-            false /* isAddSupervisedUser */
-        )
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        userSwitcherController.onUserListItemClicked(otherUserRecord, dialogShower)
-        testableLooper.processAllMessages()
-
-        verify(dialogShower).dismiss()
-    }
-
-    @Test
-    fun testAddGuest_okButtonPressed() {
-        val emptyGuestUserRecord =
-            UserRecord(
-                null,
-                null,
-                true /* guest */,
-                false /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        `when`(userManager.createGuest(any())).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(emptyGuestUserRecord, null)
-        bgExecutor.runAllReady()
-        uiExecutor.runAllReady()
-        testableLooper.processAllMessages()
-        verify(interactionJankMonitor).begin(any())
-        verify(latencyTracker).onActionStart(LatencyTracker.ACTION_USER_SWITCH)
-        verify(activityManager).switchUser(guestInfo.id)
-        assertEquals(1, uiEventLogger.numLogs())
-        assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_ADD.id, uiEventLogger.eventId(0))
-    }
-
-    @Test
-    fun testAddGuest_parentDialogDismissed() {
-        val emptyGuestUserRecord =
-            UserRecord(
-                null,
-                null,
-                true /* guest */,
-                false /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        `when`(userManager.createGuest(any())).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(emptyGuestUserRecord, dialogShower)
-        bgExecutor.runAllReady()
-        uiExecutor.runAllReady()
-        testableLooper.processAllMessages()
-        verify(dialogShower).dismiss()
-    }
-
-    @Test
-    fun testRemoveGuest_removeButtonPressed_isLogged() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                true /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestInfo.id)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
-        assertNotNull(userSwitcherController.mExitGuestDialog)
-        userSwitcherController.mExitGuestDialog
-                .getButton(DialogInterface.BUTTON_POSITIVE).performClick()
-        testableLooper.processAllMessages()
-        assertEquals(1, uiEventLogger.numLogs())
-        assertTrue(
-            QSUserSwitcherEvent.QS_USER_GUEST_REMOVE.id == uiEventLogger.eventId(0) ||
-            QSUserSwitcherEvent.QS_USER_SWITCH.id == uiEventLogger.eventId(0)
-        )
-    }
-
-    @Test
-    fun testRemoveGuest_removeButtonPressed_dialogDismissed() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                true /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestInfo.id)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
-        assertNotNull(userSwitcherController.mExitGuestDialog)
-        userSwitcherController.mExitGuestDialog
-                .getButton(DialogInterface.BUTTON_POSITIVE).performClick()
-        testableLooper.processAllMessages()
-        assertFalse(userSwitcherController.mExitGuestDialog.isShowing)
-    }
-
-    @Test
-    fun testRemoveGuest_dialogShowerUsed() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                true /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestInfo.id)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, dialogShower)
-        assertNotNull(userSwitcherController.mExitGuestDialog)
-        testableLooper.processAllMessages()
-        verify(dialogShower)
-            .showDialog(
-                userSwitcherController.mExitGuestDialog,
-                DialogCuj(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN, "exit_guest_mode"))
-    }
-
-    @Test
-    fun testRemoveGuest_cancelButtonPressed_isNotLogged() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                true /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestId)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
-        assertNotNull(userSwitcherController.mExitGuestDialog)
-        userSwitcherController.mExitGuestDialog
-                .getButton(DialogInterface.BUTTON_NEUTRAL).performClick()
-        testableLooper.processAllMessages()
-        assertEquals(0, uiEventLogger.numLogs())
-    }
-
-    @Test
-    fun testWipeGuest_startOverButtonPressed_isLogged() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                false /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestId)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        // Simulate that guest user has already logged in
-        `when`(secureSettings.getIntForUser(
-                eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt()))
-                .thenReturn(1)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
-
-        // Simulate a user switch event
-        val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
-
-        assertNotNull(userSwitcherController.mGuestResumeSessionReceiver)
-        userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent)
-
-        assertNotNull(userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog)
-        userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog
-                .getButton(GuestResumeSessionReceiver.ResetSessionDialog.BUTTON_WIPE).performClick()
-        testableLooper.processAllMessages()
-        assertEquals(1, uiEventLogger.numLogs())
-        assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_WIPE.id, uiEventLogger.eventId(0))
-    }
-
-    @Test
-    fun testWipeGuest_continueButtonPressed_isLogged() {
-        val currentGuestUserRecord =
-            UserRecord(
-                guestInfo,
-                picture,
-                true /* guest */,
-                false /* current */,
-                false /* isAddUser */,
-                false /* isRestricted */,
-                true /* isSwitchToEnabled */,
-                false /* isAddSupervisedUser */
-            )
-        `when`(userTracker.userId).thenReturn(guestId)
-        `when`(userTracker.userInfo).thenReturn(guestInfo)
-
-        // Simulate that guest user has already logged in
-        `when`(secureSettings.getIntForUser(
-                eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt()))
-                .thenReturn(1)
-
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
-
-        // Simulate a user switch event
-        val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
-
-        assertNotNull(userSwitcherController.mGuestResumeSessionReceiver)
-        userSwitcherController.mGuestResumeSessionReceiver.onReceive(context, intent)
-
-        assertNotNull(userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog)
-        userSwitcherController.mGuestResumeSessionReceiver.mNewSessionDialog
-                .getButton(GuestResumeSessionReceiver.ResetSessionDialog.BUTTON_DONTWIPE)
-                .performClick()
-        testableLooper.processAllMessages()
-        assertEquals(1, uiEventLogger.numLogs())
-        assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_CONTINUE.id, uiEventLogger.eventId(0))
-    }
-
-    @Test
-    fun test_getCurrentUserName_shouldReturnNameOfTheCurrentUser() {
-        fun addUser(id: Int, name: String, isCurrent: Boolean) {
-            userSwitcherController.users.add(
-                UserRecord(
-                    UserInfo(id, name, 0),
-                    null, false, isCurrent, false,
-                    false, false, false
-                )
-            )
-        }
-        val bgUserName = "background_user"
-        val fgUserName = "foreground_user"
-
-        addUser(1, bgUserName, false)
-        addUser(2, fgUserName, true)
-
-        assertEquals(fgUserName, userSwitcherController.currentUserName)
-    }
-
-    @Test
-    fun isSystemUser_currentUserIsSystemUser_shouldReturnTrue() {
-        `when`(userTracker.userId).thenReturn(UserHandle.USER_SYSTEM)
-        assertEquals(true, userSwitcherController.isSystemUser)
-    }
-
-    @Test
-    fun isSystemUser_currentUserIsNotSystemUser_shouldReturnFalse() {
-        `when`(userTracker.userId).thenReturn(1)
-        assertEquals(false, userSwitcherController.isSystemUser)
-    }
-
-    @Test
-    fun testCanCreateSupervisedUserWithConfiguredPackage() {
-        // GIVEN the supervised user creation package is configured
-        `when`(context.getString(
-            com.android.internal.R.string.config_supervisedUserCreationPackage))
-            .thenReturn("some_pkg")
-
-        // AND the current user is allowed to create new users
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        // WHEN the controller is started with the above config
-        setupController()
-        testableLooper.processAllMessages()
-
-        // THEN a supervised user can be constructed
-        assertTrue(userSwitcherController.canCreateSupervisedUser())
-    }
-
-    @Test
-    fun testCannotCreateSupervisedUserWithConfiguredPackage() {
-        // GIVEN the supervised user creation package is NOT configured
-        `when`(context.getString(
-            com.android.internal.R.string.config_supervisedUserCreationPackage))
-            .thenReturn(null)
-
-        // AND the current user is allowed to create new users
-        `when`(userTracker.userId).thenReturn(ownerId)
-        `when`(userTracker.userInfo).thenReturn(ownerInfo)
-
-        // WHEN the controller is started with the above config
-        setupController()
-        testableLooper.processAllMessages()
-
-        // THEN a supervised user can NOT be constructed
-        assertFalse(userSwitcherController.canCreateSupervisedUser())
-    }
-
-    @Test
-    fun testCannotCreateUserWhenUserSwitcherDisabled() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-        setupController()
-        assertFalse(userSwitcherController.canCreateUser())
-    }
-
-    @Test
-    fun testCannotCreateGuestUserWhenUserSwitcherDisabled() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-        setupController()
-        assertFalse(userSwitcherController.canCreateGuest(false))
-    }
-
-    @Test
-    fun testCannotCreateSupervisedUserWhenUserSwitcherDisabled() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-        setupController()
-        assertFalse(userSwitcherController.canCreateSupervisedUser())
-    }
-
-    @Test
-    fun testCanManageUser_userSwitcherEnabled_addUserWhenLocked() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(1)
-
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.ADD_USERS_WHEN_LOCKED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(1)
-        setupController()
-        assertTrue(userSwitcherController.canManageUsers())
-    }
-
-    @Test
-    fun testCanManageUser_userSwitcherDisabled_addUserWhenLocked() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.ADD_USERS_WHEN_LOCKED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(1)
-        setupController()
-        assertFalse(userSwitcherController.canManageUsers())
-    }
-
-    @Test
-    fun testCanManageUser_userSwitcherEnabled_isAdmin() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(1)
-
-        setupController()
-        assertTrue(userSwitcherController.canManageUsers())
-    }
-
-    @Test
-    fun testCanManageUser_userSwitcherDisabled_isAdmin() {
-        `when`(
-            globalSettings.getIntForUser(
-                eq(Settings.Global.USER_SWITCHER_ENABLED),
-                anyInt(),
-                eq(UserHandle.USER_SYSTEM)
-            )
-        ).thenReturn(0)
-
-        setupController()
-        assertFalse(userSwitcherController.canManageUsers())
-    }
-
-    @Test
-    fun addUserSwitchCallback() {
-        val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>()
-        verify(broadcastDispatcher).registerReceiver(
-                capture(broadcastReceiverCaptor),
-                any(),
-                nullable(), nullable(), anyInt(), nullable())
-
-        val cb = mock(UserSwitcherController.UserSwitchCallback::class.java)
-        userSwitcherController.addUserSwitchCallback(cb)
-
-        val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
-        broadcastReceiverCaptor.value.onReceive(context, intent)
-        verify(cb).onUserSwitched()
-    }
-
-    @Test
-    fun onUserItemClicked_guest_runsOnBgThread() {
-        val dialogShower = mock(UserSwitchDialogController.DialogShower::class.java)
-        val guestUserRecord = UserRecord(
-            null,
-            picture,
-            true /* guest */,
-            false /* current */,
-            false /* isAddUser */,
-            false /* isRestricted */,
-            true /* isSwitchToEnabled */,
-            false /* isAddSupervisedUser */
-        )
-
-        userSwitcherController.onUserListItemClicked(guestUserRecord, dialogShower)
-        assertTrue(bgExecutor.numPending() > 0)
-        verify(userManager, never()).createGuest(context)
-        bgExecutor.runAllReady()
-        verify(userManager).createGuest(context)
-    }
-
-    @Test
-    fun onUserItemClicked_manageUsers() {
-        val manageUserRecord = LegacyUserDataHelper.createRecord(
-            mContext,
-            ownerId,
-            UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-            isRestricted = false,
-            isSwitchToEnabled = true
-        )
-
-        userSwitcherController.onUserListItemClicked(manageUserRecord, null)
-        val intentCaptor = kotlinArgumentCaptor<Intent>()
-        verify(activityStarter).startActivity(intentCaptor.capture(),
-            eq(true)
-        )
-        Truth.assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
index 3fe1a9f..c06dbdc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -35,6 +35,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.ZenModeController.Callback;
 import com.android.systemui.util.settings.FakeSettings;
 
@@ -58,6 +59,8 @@
     BroadcastDispatcher mBroadcastDispatcher;
     @Mock
     DumpManager mDumpManager;
+    @Mock
+    UserTracker mUserTracker;
 
     private ZenModeControllerImpl mController;
 
@@ -72,7 +75,8 @@
                 Handler.createAsync(Looper.myLooper()),
                 mBroadcastDispatcher,
                 mDumpManager,
-                new FakeSettings());
+                new FakeSettings(),
+                mUserTracker);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ripple/MultiRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/ripple/MultiRippleControllerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
index 05512e5..0d19ab1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ripple/MultiRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.graphics.Color
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.ripple.MultiRippleController.Companion.MAX_RIPPLE_NUMBER
+import com.android.systemui.surfaceeffects.ripple.MultiRippleController.Companion.MAX_RIPPLE_NUMBER
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleViewTest.kt
new file mode 100644
index 0000000..2024d53
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleViewTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.ripple
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class MultiRippleViewTest : SysuiTestCase() {
+    private val fakeSystemClock = FakeSystemClock()
+    // FakeExecutor is needed to run animator.
+    private val fakeExecutor = FakeExecutor(fakeSystemClock)
+
+    @Test
+    fun onRippleFinishes_triggersRippleFinished() {
+        val multiRippleView = MultiRippleView(context, null)
+        val multiRippleController = MultiRippleController(multiRippleView)
+        val rippleAnimationConfig = RippleAnimationConfig(duration = 1000L)
+
+        var isTriggered = false
+        val listener =
+            object : MultiRippleView.Companion.RipplesFinishedListener {
+                override fun onRipplesFinish() {
+                    isTriggered = true
+                }
+            }
+        multiRippleView.addRipplesFinishedListener(listener)
+
+        fakeExecutor.execute {
+            val rippleAnimation = RippleAnimation(rippleAnimationConfig)
+            multiRippleController.play(rippleAnimation)
+
+            fakeSystemClock.advanceTime(rippleAnimationConfig.duration)
+
+            assertThat(isTriggered).isTrue()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ripple/RippleAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/ripple/RippleAnimationTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
index 7662282..756397a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ripple/RippleAnimationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.graphics.Color
 import android.testing.AndroidTestingRunner
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
index 2d2f4cc..1e5ab7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.ripple
+package com.android.systemui.surfaceeffects.ripple
 
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
@@ -21,12 +21,10 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 class RippleViewTest : SysuiTestCase() {
-    @Mock
     private lateinit var rippleView: RippleView
 
     @Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
new file mode 100644
index 0000000..d25c8c1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+import android.graphics.Color
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TurbulenceNoiseControllerTest : SysuiTestCase() {
+    private val fakeSystemClock = FakeSystemClock()
+    // FakeExecutor is needed to run animator.
+    private val fakeExecutor = FakeExecutor(fakeSystemClock)
+
+    @Test
+    fun play_playsTurbulenceNoise() {
+        val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+
+        val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
+
+        fakeExecutor.execute {
+            turbulenceNoiseController.play(config)
+
+            assertThat(turbulenceNoiseView.isPlaying).isTrue()
+
+            fakeSystemClock.advanceTime(config.duration.toLong())
+
+            assertThat(turbulenceNoiseView.isPlaying).isFalse()
+        }
+    }
+
+    @Test
+    fun updateColor_updatesCorrectColor() {
+        val config = TurbulenceNoiseAnimationConfig(duration = 1000f, color = Color.WHITE)
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        val expectedColor = Color.RED
+
+        val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
+
+        fakeExecutor.execute {
+            turbulenceNoiseController.play(config)
+
+            turbulenceNoiseView.updateColor(expectedColor)
+
+            fakeSystemClock.advanceTime(config.duration.toLong())
+
+            assertThat(config.color).isEqualTo(expectedColor)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
new file mode 100644
index 0000000..633aac0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.surfaceeffects.turbulencenoise
+
+import android.testing.AndroidTestingRunner
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TurbulenceNoiseViewTest : SysuiTestCase() {
+
+    private val fakeSystemClock = FakeSystemClock()
+    // FakeExecutor is needed to run animator.
+    private val fakeExecutor = FakeExecutor(fakeSystemClock)
+
+    @Test
+    fun play_viewHasCorrectVisibility() {
+        val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+
+        assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+
+        fakeExecutor.execute {
+            turbulenceNoiseView.play(config)
+
+            assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
+
+            fakeSystemClock.advanceTime(config.duration.toLong())
+
+            assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+        }
+    }
+
+    @Test
+    fun play_playsAnimation() {
+        val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+
+        fakeExecutor.execute {
+            turbulenceNoiseView.play(config)
+
+            assertThat(turbulenceNoiseView.isPlaying).isTrue()
+        }
+    }
+
+    @Test
+    fun play_onEnd_triggersOnAnimationEnd() {
+        var animationEnd = false
+        val config =
+            TurbulenceNoiseAnimationConfig(
+                duration = 1000f,
+                onAnimationEnd = { animationEnd = true }
+            )
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+
+        fakeExecutor.execute {
+            turbulenceNoiseView.play(config)
+
+            assertThat(turbulenceNoiseView.isPlaying).isTrue()
+
+            fakeSystemClock.advanceTime(config.duration.toLong())
+
+            assertThat(animationEnd).isTrue()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
index 9dea48e..09f0d4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
@@ -119,31 +119,41 @@
             )
         )
 
-        verify(logger).logViewAddition("Fake Window Title")
+        verify(logger).logViewAddition("id", "Fake Window Title")
     }
 
     @Test
-    fun displayView_screenOff_wakeLockAcquired() {
+    fun displayView_wakeLockAcquired() {
         underTest.displayView(getState())
 
         assertThat(fakeWakeLock.isHeld).isTrue()
     }
 
     @Test
-    fun displayView_screenAlreadyOn_wakeLockNotAcquired() {
+    fun displayView_screenAlreadyOn_wakeLockAcquired() {
         whenever(powerManager.isScreenOn).thenReturn(true)
 
         underTest.displayView(getState())
 
+        assertThat(fakeWakeLock.isHeld).isTrue()
+    }
+
+    @Test
+    fun displayView_wakeLockCanBeReleasedAfterTimeOut() {
+        underTest.displayView(getState())
+        assertThat(fakeWakeLock.isHeld).isTrue()
+
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
         assertThat(fakeWakeLock.isHeld).isFalse()
     }
 
     @Test
-    fun displayView_screenOff_wakeLockCanBeReleasedAfterTimeOut() {
+    fun displayView_removeView_wakeLockCanBeReleased() {
         underTest.displayView(getState())
         assertThat(fakeWakeLock.isHeld).isTrue()
 
-        fakeClock.advanceTime(TIMEOUT_MS + 1)
+        underTest.removeView("id", "test reason")
 
         assertThat(fakeWakeLock.isHeld).isFalse()
     }
@@ -253,21 +263,143 @@
     }
 
     @Test
+    fun multipleViewsWithDifferentIds_recentActiveViewIsDisplayed() {
+        underTest.displayView(ViewInfo("First name", id = "id1"))
+
+        verify(windowManager).addView(any(), any())
+
+        reset(windowManager)
+        underTest.displayView(ViewInfo("Second name", id = "id2"))
+        underTest.removeView("id2", "test reason")
+
+        verify(windowManager).removeView(any())
+
+        fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1)
+
+        assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1")
+        assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name")
+
+        reset(windowManager)
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
+        verify(windowManager).removeView(any())
+        assertThat(underTest.activeViews.size).isEqualTo(0)
+    }
+
+    @Test
+    fun multipleViewsWithDifferentIds_oldViewRemoved_recentViewIsDisplayed() {
+        underTest.displayView(ViewInfo("First name", id = "id1"))
+
+        verify(windowManager).addView(any(), any())
+
+        reset(windowManager)
+        underTest.displayView(ViewInfo("Second name", id = "id2"))
+        underTest.removeView("id1", "test reason")
+
+        verify(windowManager, never()).removeView(any())
+        assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2")
+        assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name")
+
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
+        verify(windowManager).removeView(any())
+        assertThat(underTest.activeViews.size).isEqualTo(0)
+    }
+
+    @Test
+    fun multipleViewsWithDifferentIds_threeDifferentViews_recentActiveViewIsDisplayed() {
+        underTest.displayView(ViewInfo("First name", id = "id1"))
+        underTest.displayView(ViewInfo("Second name", id = "id2"))
+        underTest.displayView(ViewInfo("Third name", id = "id3"))
+
+        verify(windowManager).addView(any(), any())
+
+        reset(windowManager)
+        underTest.removeView("id3", "test reason")
+
+        verify(windowManager).removeView(any())
+
+        fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1)
+
+        assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2")
+        assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name")
+
+        reset(windowManager)
+        underTest.removeView("id2", "test reason")
+
+        verify(windowManager).removeView(any())
+
+        fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1)
+
+        assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1")
+        assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name")
+
+        reset(windowManager)
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
+        verify(windowManager).removeView(any())
+        assertThat(underTest.activeViews.size).isEqualTo(0)
+    }
+
+    @Test
+    fun multipleViewsWithDifferentIds_oneViewStateChanged_stackHasRecentState() {
+        underTest.displayView(ViewInfo("First name", id = "id1"))
+        underTest.displayView(ViewInfo("New name", id = "id1"))
+
+        verify(windowManager).addView(any(), any())
+
+        reset(windowManager)
+        underTest.displayView(ViewInfo("Second name", id = "id2"))
+        underTest.removeView("id2", "test reason")
+
+        verify(windowManager).removeView(any())
+
+        fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1)
+
+        assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1")
+        assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("New name")
+        assertThat(underTest.activeViews[0].second.name).isEqualTo("New name")
+
+        reset(windowManager)
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
+        verify(windowManager).removeView(any())
+        assertThat(underTest.activeViews.size).isEqualTo(0)
+    }
+
+    @Test
+    fun multipleViewsWithDifferentIds_viewsTimeouts_noViewLeftToDisplay() {
+        underTest.displayView(ViewInfo("First name", id = "id1"))
+        fakeClock.advanceTime(TIMEOUT_MS / 3)
+        underTest.displayView(ViewInfo("Second name", id = "id2"))
+        fakeClock.advanceTime(TIMEOUT_MS / 3)
+        underTest.displayView(ViewInfo("Third name", id = "id3"))
+
+        reset(windowManager)
+        fakeClock.advanceTime(TIMEOUT_MS + 1)
+
+        verify(windowManager).removeView(any())
+        verify(windowManager, never()).addView(any(), any())
+        assertThat(underTest.activeViews.size).isEqualTo(0)
+    }
+
+    @Test
     fun removeView_viewRemovedAndRemovalLogged() {
         // First, add the view
         underTest.displayView(getState())
 
         // Then, remove it
         val reason = "test reason"
-        underTest.removeView(reason)
+        val deviceId = "id"
+        underTest.removeView(deviceId, reason)
 
         verify(windowManager).removeView(any())
-        verify(logger).logViewRemoval(reason)
+        verify(logger).logViewRemoval(deviceId, reason)
     }
 
     @Test
     fun removeView_noAdd_viewNotRemoved() {
-        underTest.removeView("reason")
+        underTest.removeView("id", "reason")
 
         verify(windowManager, never()).removeView(any())
     }
@@ -319,7 +451,8 @@
         val name: String,
         override val windowTitle: String = "Window Title",
         override val wakeReason: String = "WAKE_REASON",
-        override val timeoutMs: Int = 1
+        override val timeoutMs: Int = 1,
+        override val id: String = "id",
     ) : TemporaryViewInfo()
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
index d155050..116b8fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
@@ -44,7 +44,7 @@
 
     @Test
     fun logViewAddition_bufferHasLog() {
-        logger.logViewAddition("Test Window Title")
+        logger.logViewAddition("test id", "Test Window Title")
 
         val stringWriter = StringWriter()
         buffer.dump(PrintWriter(stringWriter), tailLength = 0)
@@ -57,7 +57,8 @@
     @Test
     fun logViewRemoval_bufferHasTagAndReason() {
         val reason = "test reason"
-        logger.logViewRemoval(reason)
+        val deviceId = "test id"
+        logger.logViewRemoval(deviceId, reason)
 
         val stringWriter = StringWriter()
         buffer.dump(PrintWriter(stringWriter), tailLength = 0)
@@ -65,6 +66,7 @@
 
         assertThat(actualString).contains(TAG)
         assertThat(actualString).contains(reason)
+        assertThat(actualString).contains(deviceId)
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
index 8e37aa2..47c84ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
@@ -377,6 +377,7 @@
             windowTitle = WINDOW_TITLE,
             wakeReason = WAKE_REASON,
             timeoutMs = TIMEOUT,
+            id = DEVICE_ID,
         )
     }
 
@@ -401,3 +402,4 @@
 private const val TIMEOUT = 10000
 private const val WINDOW_TITLE = "Test Chipbar Window Title"
 private const val WAKE_REASON = "TEST_CHIPBAR_WAKE_REASON"
+private const val DEVICE_ID = "id"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt
deleted file mode 100644
index 7c7f0e1..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.user.data.repository
-
-import android.content.pm.UserInfo
-import android.os.UserHandle
-import android.os.UserManager
-import android.provider.Settings
-import androidx.test.filters.SmallTest
-import com.android.systemui.user.data.model.UserSwitcherSettingsModel
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(JUnit4::class)
-class UserRepositoryImplRefactoredTest : UserRepositoryImplTest() {
-
-    @Before
-    fun setUp() {
-        super.setUp(isRefactored = true)
-    }
-
-    @Test
-    fun userSwitcherSettings() = runSelfCancelingTest {
-        setUpGlobalSettings(
-            isSimpleUserSwitcher = true,
-            isAddUsersFromLockscreen = true,
-            isUserSwitcherEnabled = true,
-        )
-        underTest = create(this)
-
-        var value: UserSwitcherSettingsModel? = null
-        underTest.userSwitcherSettings.onEach { value = it }.launchIn(this)
-
-        assertUserSwitcherSettings(
-            model = value,
-            expectedSimpleUserSwitcher = true,
-            expectedAddUsersFromLockscreen = true,
-            expectedUserSwitcherEnabled = true,
-        )
-
-        setUpGlobalSettings(
-            isSimpleUserSwitcher = false,
-            isAddUsersFromLockscreen = true,
-            isUserSwitcherEnabled = true,
-        )
-        assertUserSwitcherSettings(
-            model = value,
-            expectedSimpleUserSwitcher = false,
-            expectedAddUsersFromLockscreen = true,
-            expectedUserSwitcherEnabled = true,
-        )
-    }
-
-    @Test
-    fun refreshUsers() = runSelfCancelingTest {
-        underTest = create(this)
-        val initialExpectedValue =
-            setUpUsers(
-                count = 3,
-                selectedIndex = 0,
-            )
-        var userInfos: List<UserInfo>? = null
-        var selectedUserInfo: UserInfo? = null
-        underTest.userInfos.onEach { userInfos = it }.launchIn(this)
-        underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
-
-        underTest.refreshUsers()
-        assertThat(userInfos).isEqualTo(initialExpectedValue)
-        assertThat(selectedUserInfo).isEqualTo(initialExpectedValue[0])
-        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
-
-        val secondExpectedValue =
-            setUpUsers(
-                count = 4,
-                selectedIndex = 1,
-            )
-        underTest.refreshUsers()
-        assertThat(userInfos).isEqualTo(secondExpectedValue)
-        assertThat(selectedUserInfo).isEqualTo(secondExpectedValue[1])
-        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
-
-        val selectedNonGuestUserId = selectedUserInfo?.id
-        val thirdExpectedValue =
-            setUpUsers(
-                count = 2,
-                isLastGuestUser = true,
-                selectedIndex = 1,
-            )
-        underTest.refreshUsers()
-        assertThat(userInfos).isEqualTo(thirdExpectedValue)
-        assertThat(selectedUserInfo).isEqualTo(thirdExpectedValue[1])
-        assertThat(selectedUserInfo?.isGuest).isTrue()
-        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedNonGuestUserId)
-    }
-
-    @Test
-    fun `refreshUsers - sorts by creation time - guest user last`() = runSelfCancelingTest {
-        underTest = create(this)
-        val unsortedUsers =
-            setUpUsers(
-                count = 3,
-                selectedIndex = 0,
-                isLastGuestUser = true,
-            )
-        unsortedUsers[0].creationTime = 999
-        unsortedUsers[1].creationTime = 900
-        unsortedUsers[2].creationTime = 950
-        val expectedUsers =
-            listOf(
-                unsortedUsers[1],
-                unsortedUsers[0],
-                unsortedUsers[2], // last because this is the guest
-            )
-        var userInfos: List<UserInfo>? = null
-        underTest.userInfos.onEach { userInfos = it }.launchIn(this)
-
-        underTest.refreshUsers()
-        assertThat(userInfos).isEqualTo(expectedUsers)
-    }
-
-    @Test
-    fun `userTrackerCallback - updates selectedUserInfo`() = runSelfCancelingTest {
-        underTest = create(this)
-        var selectedUserInfo: UserInfo? = null
-        underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
-        setUpUsers(
-            count = 2,
-            selectedIndex = 0,
-        )
-        tracker.onProfileChanged()
-        assertThat(selectedUserInfo?.id == 0)
-        setUpUsers(
-            count = 2,
-            selectedIndex = 1,
-        )
-        tracker.onProfileChanged()
-        assertThat(selectedUserInfo?.id == 1)
-    }
-
-    private fun setUpUsers(
-        count: Int,
-        isLastGuestUser: Boolean = false,
-        selectedIndex: Int = 0,
-    ): List<UserInfo> {
-        val userInfos =
-            (0 until count).map { index ->
-                createUserInfo(
-                    index,
-                    isGuest = isLastGuestUser && index == count - 1,
-                )
-            }
-        whenever(manager.aliveUsers).thenReturn(userInfos)
-        tracker.set(userInfos, selectedIndex)
-        return userInfos
-    }
-
-    private fun createUserInfo(
-        id: Int,
-        isGuest: Boolean,
-    ): UserInfo {
-        val flags = 0
-        return UserInfo(
-            id,
-            "user_$id",
-            /* iconPath= */ "",
-            flags,
-            if (isGuest) UserManager.USER_TYPE_FULL_GUEST else UserInfo.getDefaultUserType(flags),
-        )
-    }
-
-    private fun setUpGlobalSettings(
-        isSimpleUserSwitcher: Boolean = false,
-        isAddUsersFromLockscreen: Boolean = false,
-        isUserSwitcherEnabled: Boolean = true,
-    ) {
-        context.orCreateTestableResources.addOverride(
-            com.android.internal.R.bool.config_expandLockScreenUserSwitcher,
-            true,
-        )
-        globalSettings.putIntForUser(
-            UserRepositoryImpl.SETTING_SIMPLE_USER_SWITCHER,
-            if (isSimpleUserSwitcher) 1 else 0,
-            UserHandle.USER_SYSTEM,
-        )
-        globalSettings.putIntForUser(
-            Settings.Global.ADD_USERS_WHEN_LOCKED,
-            if (isAddUsersFromLockscreen) 1 else 0,
-            UserHandle.USER_SYSTEM,
-        )
-        globalSettings.putIntForUser(
-            Settings.Global.USER_SWITCHER_ENABLED,
-            if (isUserSwitcherEnabled) 1 else 0,
-            UserHandle.USER_SYSTEM,
-        )
-    }
-
-    private fun assertUserSwitcherSettings(
-        model: UserSwitcherSettingsModel?,
-        expectedSimpleUserSwitcher: Boolean,
-        expectedAddUsersFromLockscreen: Boolean,
-        expectedUserSwitcherEnabled: Boolean,
-    ) {
-        checkNotNull(model)
-        assertThat(model.isSimpleUserSwitcher).isEqualTo(expectedSimpleUserSwitcher)
-        assertThat(model.isAddUsersFromLockscreen).isEqualTo(expectedAddUsersFromLockscreen)
-        assertThat(model.isUserSwitcherEnabled).isEqualTo(expectedUserSwitcherEnabled)
-    }
-
-    /**
-     * Executes the given block of execution within the scope of a dedicated [CoroutineScope] which
-     * is then automatically canceled and cleaned-up.
-     */
-    private fun runSelfCancelingTest(
-        block: suspend CoroutineScope.() -> Unit,
-    ) =
-        runBlocking(Dispatchers.Main.immediate) {
-            val scope = CoroutineScope(coroutineContext + Job())
-            block(scope)
-            scope.cancel()
-        }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index dcea83a..2e527be1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,54 +17,263 @@
 
 package com.android.systemui.user.data.repository
 
+import android.content.pm.UserInfo
+import android.os.UserHandle
 import android.os.UserManager
+import android.provider.Settings
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.settings.FakeUserTracker
-import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.TestCoroutineScope
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
 import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
-abstract class UserRepositoryImplTest : SysuiTestCase() {
+@SmallTest
+@RunWith(JUnit4::class)
+class UserRepositoryImplTest : SysuiTestCase() {
 
-    @Mock protected lateinit var manager: UserManager
-    @Mock protected lateinit var controller: UserSwitcherController
+    @Mock private lateinit var manager: UserManager
 
-    protected lateinit var underTest: UserRepositoryImpl
+    private lateinit var underTest: UserRepositoryImpl
 
-    protected lateinit var globalSettings: FakeSettings
-    protected lateinit var tracker: FakeUserTracker
-    protected lateinit var featureFlags: FakeFeatureFlags
+    private lateinit var globalSettings: FakeSettings
+    private lateinit var tracker: FakeUserTracker
 
-    protected fun setUp(isRefactored: Boolean) {
+    @Before
+    fun setUp() {
         MockitoAnnotations.initMocks(this)
 
         globalSettings = FakeSettings()
         tracker = FakeUserTracker()
-        featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER, !isRefactored)
     }
 
-    protected fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
+    @Test
+    fun userSwitcherSettings() = runSelfCancelingTest {
+        setUpGlobalSettings(
+            isSimpleUserSwitcher = true,
+            isAddUsersFromLockscreen = true,
+            isUserSwitcherEnabled = true,
+        )
+        underTest = create(this)
+
+        var value: UserSwitcherSettingsModel? = null
+        underTest.userSwitcherSettings.onEach { value = it }.launchIn(this)
+
+        assertUserSwitcherSettings(
+            model = value,
+            expectedSimpleUserSwitcher = true,
+            expectedAddUsersFromLockscreen = true,
+            expectedUserSwitcherEnabled = true,
+        )
+
+        setUpGlobalSettings(
+            isSimpleUserSwitcher = false,
+            isAddUsersFromLockscreen = true,
+            isUserSwitcherEnabled = true,
+        )
+        assertUserSwitcherSettings(
+            model = value,
+            expectedSimpleUserSwitcher = false,
+            expectedAddUsersFromLockscreen = true,
+            expectedUserSwitcherEnabled = true,
+        )
+    }
+
+    @Test
+    fun refreshUsers() = runSelfCancelingTest {
+        underTest = create(this)
+        val initialExpectedValue =
+            setUpUsers(
+                count = 3,
+                selectedIndex = 0,
+            )
+        var userInfos: List<UserInfo>? = null
+        var selectedUserInfo: UserInfo? = null
+        underTest.userInfos.onEach { userInfos = it }.launchIn(this)
+        underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
+
+        underTest.refreshUsers()
+        assertThat(userInfos).isEqualTo(initialExpectedValue)
+        assertThat(selectedUserInfo).isEqualTo(initialExpectedValue[0])
+        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
+
+        val secondExpectedValue =
+            setUpUsers(
+                count = 4,
+                selectedIndex = 1,
+            )
+        underTest.refreshUsers()
+        assertThat(userInfos).isEqualTo(secondExpectedValue)
+        assertThat(selectedUserInfo).isEqualTo(secondExpectedValue[1])
+        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
+
+        val selectedNonGuestUserId = selectedUserInfo?.id
+        val thirdExpectedValue =
+            setUpUsers(
+                count = 2,
+                isLastGuestUser = true,
+                selectedIndex = 1,
+            )
+        underTest.refreshUsers()
+        assertThat(userInfos).isEqualTo(thirdExpectedValue)
+        assertThat(selectedUserInfo).isEqualTo(thirdExpectedValue[1])
+        assertThat(selectedUserInfo?.isGuest).isTrue()
+        assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedNonGuestUserId)
+    }
+
+    @Test
+    fun `refreshUsers - sorts by creation time - guest user last`() = runSelfCancelingTest {
+        underTest = create(this)
+        val unsortedUsers =
+            setUpUsers(
+                count = 3,
+                selectedIndex = 0,
+                isLastGuestUser = true,
+            )
+        unsortedUsers[0].creationTime = 999
+        unsortedUsers[1].creationTime = 900
+        unsortedUsers[2].creationTime = 950
+        val expectedUsers =
+            listOf(
+                unsortedUsers[1],
+                unsortedUsers[0],
+                unsortedUsers[2], // last because this is the guest
+            )
+        var userInfos: List<UserInfo>? = null
+        underTest.userInfos.onEach { userInfos = it }.launchIn(this)
+
+        underTest.refreshUsers()
+        assertThat(userInfos).isEqualTo(expectedUsers)
+    }
+
+    private fun setUpUsers(
+        count: Int,
+        isLastGuestUser: Boolean = false,
+        selectedIndex: Int = 0,
+    ): List<UserInfo> {
+        val userInfos =
+            (0 until count).map { index ->
+                createUserInfo(
+                    index,
+                    isGuest = isLastGuestUser && index == count - 1,
+                )
+            }
+        whenever(manager.aliveUsers).thenReturn(userInfos)
+        tracker.set(userInfos, selectedIndex)
+        return userInfos
+    }
+    @Test
+    fun `userTrackerCallback - updates selectedUserInfo`() = runSelfCancelingTest {
+        underTest = create(this)
+        var selectedUserInfo: UserInfo? = null
+        underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
+        setUpUsers(
+            count = 2,
+            selectedIndex = 0,
+        )
+        tracker.onProfileChanged()
+        assertThat(selectedUserInfo?.id).isEqualTo(0)
+        setUpUsers(
+            count = 2,
+            selectedIndex = 1,
+        )
+        tracker.onProfileChanged()
+        assertThat(selectedUserInfo?.id).isEqualTo(1)
+    }
+
+    private fun createUserInfo(
+        id: Int,
+        isGuest: Boolean,
+    ): UserInfo {
+        val flags = 0
+        return UserInfo(
+            id,
+            "user_$id",
+            /* iconPath= */ "",
+            flags,
+            if (isGuest) UserManager.USER_TYPE_FULL_GUEST else UserInfo.getDefaultUserType(flags),
+        )
+    }
+
+    private fun setUpGlobalSettings(
+        isSimpleUserSwitcher: Boolean = false,
+        isAddUsersFromLockscreen: Boolean = false,
+        isUserSwitcherEnabled: Boolean = true,
+    ) {
+        context.orCreateTestableResources.addOverride(
+            com.android.internal.R.bool.config_expandLockScreenUserSwitcher,
+            true,
+        )
+        globalSettings.putIntForUser(
+            UserRepositoryImpl.SETTING_SIMPLE_USER_SWITCHER,
+            if (isSimpleUserSwitcher) 1 else 0,
+            UserHandle.USER_SYSTEM,
+        )
+        globalSettings.putIntForUser(
+            Settings.Global.ADD_USERS_WHEN_LOCKED,
+            if (isAddUsersFromLockscreen) 1 else 0,
+            UserHandle.USER_SYSTEM,
+        )
+        globalSettings.putIntForUser(
+            Settings.Global.USER_SWITCHER_ENABLED,
+            if (isUserSwitcherEnabled) 1 else 0,
+            UserHandle.USER_SYSTEM,
+        )
+    }
+
+    private fun assertUserSwitcherSettings(
+        model: UserSwitcherSettingsModel?,
+        expectedSimpleUserSwitcher: Boolean,
+        expectedAddUsersFromLockscreen: Boolean,
+        expectedUserSwitcherEnabled: Boolean,
+    ) {
+        checkNotNull(model)
+        assertThat(model.isSimpleUserSwitcher).isEqualTo(expectedSimpleUserSwitcher)
+        assertThat(model.isAddUsersFromLockscreen).isEqualTo(expectedAddUsersFromLockscreen)
+        assertThat(model.isUserSwitcherEnabled).isEqualTo(expectedUserSwitcherEnabled)
+    }
+
+    /**
+     * Executes the given block of execution within the scope of a dedicated [CoroutineScope] which
+     * is then automatically canceled and cleaned-up.
+     */
+    private fun runSelfCancelingTest(
+        block: suspend CoroutineScope.() -> Unit,
+    ) =
+        runBlocking(Dispatchers.Main.immediate) {
+            val scope = CoroutineScope(coroutineContext + Job())
+            block(scope)
+            scope.cancel()
+        }
+
+    private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
         return UserRepositoryImpl(
             appContext = context,
             manager = manager,
-            controller = controller,
             applicationScope = scope,
             mainDispatcher = IMMEDIATE,
             backgroundDispatcher = IMMEDIATE,
             globalSettings = globalSettings,
             tracker = tracker,
-            featureFlags = featureFlags,
         )
     }
 
     companion object {
-        @JvmStatic protected val IMMEDIATE = Dispatchers.Main.immediate
+        @JvmStatic private val IMMEDIATE = Dispatchers.Main.immediate
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplUnrefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplUnrefactoredTest.kt
deleted file mode 100644
index a363a03..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplUnrefactoredTest.kt
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.user.data.repository
-
-import android.content.pm.UserInfo
-import androidx.test.filters.SmallTest
-import com.android.systemui.statusbar.policy.UserSwitcherController
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.user.shared.model.UserModel
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.capture
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(JUnit4::class)
-class UserRepositoryImplUnrefactoredTest : UserRepositoryImplTest() {
-
-    companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
-    }
-
-    @Captor
-    private lateinit var userSwitchCallbackCaptor:
-        ArgumentCaptor<UserSwitcherController.UserSwitchCallback>
-
-    @Before
-    fun setUp() {
-        super.setUp(isRefactored = false)
-
-        whenever(controller.isAddUsersFromLockScreenEnabled).thenReturn(MutableStateFlow(false))
-        whenever(controller.isGuestUserAutoCreated).thenReturn(false)
-        whenever(controller.isGuestUserResetting).thenReturn(false)
-
-        underTest = create()
-    }
-
-    @Test
-    fun `users - registers for updates`() =
-        runBlocking(IMMEDIATE) {
-            val job = underTest.users.onEach {}.launchIn(this)
-
-            verify(controller).addUserSwitchCallback(any())
-
-            job.cancel()
-        }
-
-    @Test
-    fun `users - unregisters from updates`() =
-        runBlocking(IMMEDIATE) {
-            val job = underTest.users.onEach {}.launchIn(this)
-            verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor))
-
-            job.cancel()
-
-            verify(controller).removeUserSwitchCallback(userSwitchCallbackCaptor.value)
-        }
-
-    @Test
-    fun `users - does not include actions`() =
-        runBlocking(IMMEDIATE) {
-            whenever(controller.users)
-                .thenReturn(
-                    arrayListOf(
-                        createUserRecord(0, isSelected = true),
-                        createActionRecord(UserActionModel.ADD_USER),
-                        createUserRecord(1),
-                        createUserRecord(2),
-                        createActionRecord(UserActionModel.ADD_SUPERVISED_USER),
-                        createActionRecord(UserActionModel.ENTER_GUEST_MODE),
-                        createActionRecord(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT),
-                    )
-                )
-            var models: List<UserModel>? = null
-            val job = underTest.users.onEach { models = it }.launchIn(this)
-
-            assertThat(models).hasSize(3)
-            assertThat(models?.get(0)?.id).isEqualTo(0)
-            assertThat(models?.get(0)?.isSelected).isTrue()
-            assertThat(models?.get(1)?.id).isEqualTo(1)
-            assertThat(models?.get(1)?.isSelected).isFalse()
-            assertThat(models?.get(2)?.id).isEqualTo(2)
-            assertThat(models?.get(2)?.isSelected).isFalse()
-            job.cancel()
-        }
-
-    @Test
-    fun selectedUser() =
-        runBlocking(IMMEDIATE) {
-            whenever(controller.users)
-                .thenReturn(
-                    arrayListOf(
-                        createUserRecord(0, isSelected = true),
-                        createUserRecord(1),
-                        createUserRecord(2),
-                    )
-                )
-            var id: Int? = null
-            val job = underTest.selectedUser.map { it.id }.onEach { id = it }.launchIn(this)
-
-            assertThat(id).isEqualTo(0)
-
-            whenever(controller.users)
-                .thenReturn(
-                    arrayListOf(
-                        createUserRecord(0),
-                        createUserRecord(1),
-                        createUserRecord(2, isSelected = true),
-                    )
-                )
-            verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor))
-            userSwitchCallbackCaptor.value.onUserSwitched()
-            assertThat(id).isEqualTo(2)
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - unregisters from updates`() =
-        runBlocking(IMMEDIATE) {
-            val job = underTest.actions.onEach {}.launchIn(this)
-            verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor))
-
-            job.cancel()
-
-            verify(controller).removeUserSwitchCallback(userSwitchCallbackCaptor.value)
-        }
-
-    @Test
-    fun `actions - registers for updates`() =
-        runBlocking(IMMEDIATE) {
-            val job = underTest.actions.onEach {}.launchIn(this)
-
-            verify(controller).addUserSwitchCallback(any())
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - does not include users`() =
-        runBlocking(IMMEDIATE) {
-            whenever(controller.users)
-                .thenReturn(
-                    arrayListOf(
-                        createUserRecord(0, isSelected = true),
-                        createActionRecord(UserActionModel.ADD_USER),
-                        createUserRecord(1),
-                        createUserRecord(2),
-                        createActionRecord(UserActionModel.ADD_SUPERVISED_USER),
-                        createActionRecord(UserActionModel.ENTER_GUEST_MODE),
-                        createActionRecord(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT),
-                    )
-                )
-            var models: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { models = it }.launchIn(this)
-
-            assertThat(models).hasSize(4)
-            assertThat(models?.get(0)).isEqualTo(UserActionModel.ADD_USER)
-            assertThat(models?.get(1)).isEqualTo(UserActionModel.ADD_SUPERVISED_USER)
-            assertThat(models?.get(2)).isEqualTo(UserActionModel.ENTER_GUEST_MODE)
-            assertThat(models?.get(3)).isEqualTo(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
-            job.cancel()
-        }
-
-    private fun createUserRecord(id: Int, isSelected: Boolean = false): UserRecord {
-        return UserRecord(
-            info = UserInfo(id, "name$id", 0),
-            isCurrent = isSelected,
-        )
-    }
-
-    private fun createActionRecord(action: UserActionModel): UserRecord {
-        return UserRecord(
-            isAddUser = action == UserActionModel.ADD_USER,
-            isAddSupervisedUser = action == UserActionModel.ADD_SUPERVISED_USER,
-            isGuest = action == UserActionModel.ENTER_GUEST_MODE,
-            isManageUsers = action == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-        )
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt
deleted file mode 100644
index f682e31..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.user.domain.interactor
-
-import android.content.Intent
-import android.content.pm.UserInfo
-import android.graphics.Bitmap
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.os.UserManager
-import android.provider.Settings
-import androidx.test.filters.SmallTest
-import com.android.internal.R.drawable.ic_account_circle
-import com.android.systemui.R
-import com.android.systemui.common.shared.model.Text
-import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.user.data.model.UserSwitcherSettingsModel
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.user.domain.model.ShowDialogRequestModel
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.user.shared.model.UserModel
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.kotlinArgumentCaptor
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.advanceUntilIdle
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-
-@SmallTest
-@RunWith(JUnit4::class)
-class UserInteractorRefactoredTest : UserInteractorTest() {
-
-    override fun isRefactored(): Boolean {
-        return true
-    }
-
-    @Before
-    override fun setUp() {
-        super.setUp()
-
-        overrideResource(R.drawable.ic_account_circle, GUEST_ICON)
-        overrideResource(R.dimen.max_avatar_size, 10)
-        overrideResource(
-            com.android.internal.R.string.config_supervisedUserCreationPackage,
-            SUPERVISED_USER_CREATION_APP_PACKAGE,
-        )
-        whenever(manager.getUserIcon(anyInt())).thenReturn(ICON)
-        whenever(manager.canAddMoreUsers(any())).thenReturn(true)
-    }
-
-    @Test
-    fun `onRecordSelected - user`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            underTest.onRecordSelected(UserRecord(info = userInfos[1]), dialogShower)
-
-            verify(dialogShower).dismiss()
-            verify(activityManager).switchUser(userInfos[1].id)
-            Unit
-        }
-
-    @Test
-    fun `onRecordSelected - switch to guest user`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = true)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            underTest.onRecordSelected(UserRecord(info = userInfos.last()))
-
-            verify(activityManager).switchUser(userInfos.last().id)
-            Unit
-        }
-
-    @Test
-    fun `onRecordSelected - enter guest mode`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true)
-            whenever(manager.createGuest(any())).thenReturn(guestUserInfo)
-
-            underTest.onRecordSelected(UserRecord(isGuest = true), dialogShower)
-
-            verify(dialogShower).dismiss()
-            verify(manager).createGuest(any())
-            Unit
-        }
-
-    @Test
-    fun `onRecordSelected - action`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = true)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            underTest.onRecordSelected(UserRecord(isAddSupervisedUser = true), dialogShower)
-
-            verify(dialogShower, never()).dismiss()
-            verify(activityStarter).startActivity(any(), anyBoolean())
-        }
-
-    @Test
-    fun `users - switcher enabled`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = true)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            var value: List<UserModel>? = null
-            val job = underTest.users.onEach { value = it }.launchIn(this)
-            assertUsers(models = value, count = 3, includeGuest = true)
-
-            job.cancel()
-        }
-
-    @Test
-    fun `users - switches to second user`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            var value: List<UserModel>? = null
-            val job = underTest.users.onEach { value = it }.launchIn(this)
-            userRepository.setSelectedUserInfo(userInfos[1])
-
-            assertUsers(models = value, count = 2, selectedIndex = 1)
-            job.cancel()
-        }
-
-    @Test
-    fun `users - switcher not enabled`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false))
-
-            var value: List<UserModel>? = null
-            val job = underTest.users.onEach { value = it }.launchIn(this)
-            assertUsers(models = value, count = 1)
-
-            job.cancel()
-        }
-
-    @Test
-    fun selectedUser() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-
-            var value: UserModel? = null
-            val job = underTest.selectedUser.onEach { value = it }.launchIn(this)
-            assertUser(value, id = 0, isSelected = true)
-
-            userRepository.setSelectedUserInfo(userInfos[1])
-            assertUser(value, id = 1, isSelected = true)
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - device unlocked`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            keyguardRepository.setKeyguardShowing(false)
-            var value: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { value = it }.launchIn(this)
-
-            assertThat(value)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    )
-                )
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - device unlocked user not primary - empty list`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[1])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            keyguardRepository.setKeyguardShowing(false)
-            var value: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { value = it }.launchIn(this)
-
-            assertThat(value).isEqualTo(emptyList<UserActionModel>())
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - device unlocked user is guest - empty list`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = true)
-            assertThat(userInfos[1].isGuest).isTrue()
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[1])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            keyguardRepository.setKeyguardShowing(false)
-            var value: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { value = it }.launchIn(this)
-
-            assertThat(value).isEqualTo(emptyList<UserActionModel>())
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - device locked add from lockscreen set - full list`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(
-                UserSwitcherSettingsModel(
-                    isUserSwitcherEnabled = true,
-                    isAddUsersFromLockscreen = true,
-                )
-            )
-            keyguardRepository.setKeyguardShowing(false)
-            var value: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { value = it }.launchIn(this)
-
-            assertThat(value)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    )
-                )
-
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - device locked - only guest action and manage user is shown`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            keyguardRepository.setKeyguardShowing(true)
-            var value: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { value = it }.launchIn(this)
-
-            assertThat(value)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
-                    )
-                )
-
-            job.cancel()
-        }
-
-    @Test
-    fun `executeAction - add user - dialog shown`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            keyguardRepository.setKeyguardShowing(false)
-            var dialogRequest: ShowDialogRequestModel? = null
-            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
-            val dialogShower: UserSwitchDialogController.DialogShower = mock()
-
-            underTest.executeAction(UserActionModel.ADD_USER, dialogShower)
-            assertThat(dialogRequest)
-                .isEqualTo(
-                    ShowDialogRequestModel.ShowAddUserDialog(
-                        userHandle = userInfos[0].userHandle,
-                        isKeyguardShowing = false,
-                        showEphemeralMessage = false,
-                        dialogShower = dialogShower,
-                    )
-                )
-
-            underTest.onDialogShown()
-            assertThat(dialogRequest).isNull()
-
-            job.cancel()
-        }
-
-    @Test
-    fun `executeAction - add supervised user - starts activity`() =
-        runBlocking(IMMEDIATE) {
-            underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
-
-            val intentCaptor = kotlinArgumentCaptor<Intent>()
-            verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
-            assertThat(intentCaptor.value.action)
-                .isEqualTo(UserManager.ACTION_CREATE_SUPERVISED_USER)
-            assertThat(intentCaptor.value.`package`).isEqualTo(SUPERVISED_USER_CREATION_APP_PACKAGE)
-        }
-
-    @Test
-    fun `executeAction - navigate to manage users`() =
-        runBlocking(IMMEDIATE) {
-            underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
-
-            val intentCaptor = kotlinArgumentCaptor<Intent>()
-            verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
-            assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
-        }
-
-    @Test
-    fun `executeAction - guest mode`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true)
-            whenever(manager.createGuest(any())).thenReturn(guestUserInfo)
-            val dialogRequests = mutableListOf<ShowDialogRequestModel?>()
-            val showDialogsJob =
-                underTest.dialogShowRequests
-                    .onEach {
-                        dialogRequests.add(it)
-                        if (it != null) {
-                            underTest.onDialogShown()
-                        }
-                    }
-                    .launchIn(this)
-            val dismissDialogsJob =
-                underTest.dialogDismissRequests
-                    .onEach {
-                        if (it != null) {
-                            underTest.onDialogDismissed()
-                        }
-                    }
-                    .launchIn(this)
-
-            underTest.executeAction(UserActionModel.ENTER_GUEST_MODE)
-
-            assertThat(dialogRequests)
-                .contains(
-                    ShowDialogRequestModel.ShowUserCreationDialog(isGuest = true),
-                )
-            verify(activityManager).switchUser(guestUserInfo.id)
-
-            showDialogsJob.cancel()
-            dismissDialogsJob.cancel()
-        }
-
-    @Test
-    fun `selectUser - already selected guest re-selected - exit guest dialog`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = true)
-            val guestUserInfo = userInfos[1]
-            assertThat(guestUserInfo.isGuest).isTrue()
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(guestUserInfo)
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            var dialogRequest: ShowDialogRequestModel? = null
-            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
-
-            underTest.selectUser(
-                newlySelectedUserId = guestUserInfo.id,
-                dialogShower = dialogShower,
-            )
-
-            assertThat(dialogRequest)
-                .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
-            verify(dialogShower, never()).dismiss()
-            job.cancel()
-        }
-
-    @Test
-    fun `selectUser - currently guest non-guest selected - exit guest dialog`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = true)
-            val guestUserInfo = userInfos[1]
-            assertThat(guestUserInfo.isGuest).isTrue()
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(guestUserInfo)
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            var dialogRequest: ShowDialogRequestModel? = null
-            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
-
-            underTest.selectUser(newlySelectedUserId = userInfos[0].id, dialogShower = dialogShower)
-
-            assertThat(dialogRequest)
-                .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
-            verify(dialogShower, never()).dismiss()
-            job.cancel()
-        }
-
-    @Test
-    fun `selectUser - not currently guest - switches users`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            var dialogRequest: ShowDialogRequestModel? = null
-            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
-
-            underTest.selectUser(newlySelectedUserId = userInfos[1].id, dialogShower = dialogShower)
-
-            assertThat(dialogRequest).isNull()
-            verify(activityManager).switchUser(userInfos[1].id)
-            verify(dialogShower).dismiss()
-            job.cancel()
-        }
-
-    @Test
-    fun `Telephony call state changes - refreshes users`() =
-        runBlocking(IMMEDIATE) {
-            val refreshUsersCallCount = userRepository.refreshUsersCallCount
-
-            telephonyRepository.setCallState(1)
-
-            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
-        }
-
-    @Test
-    fun `User switched broadcast`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            val callback1: UserInteractor.UserCallback = mock()
-            val callback2: UserInteractor.UserCallback = mock()
-            underTest.addCallback(callback1)
-            underTest.addCallback(callback2)
-            val refreshUsersCallCount = userRepository.refreshUsersCallCount
-
-            userRepository.setSelectedUserInfo(userInfos[1])
-            fakeBroadcastDispatcher.registeredReceivers.forEach {
-                it.onReceive(
-                    context,
-                    Intent(Intent.ACTION_USER_SWITCHED)
-                        .putExtra(Intent.EXTRA_USER_HANDLE, userInfos[1].id),
-                )
-            }
-
-            verify(callback1).onUserStateChanged()
-            verify(callback2).onUserStateChanged()
-            assertThat(userRepository.secondaryUserId).isEqualTo(userInfos[1].id)
-            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
-        }
-
-    @Test
-    fun `User info changed broadcast`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            val refreshUsersCallCount = userRepository.refreshUsersCallCount
-
-            fakeBroadcastDispatcher.registeredReceivers.forEach {
-                it.onReceive(
-                    context,
-                    Intent(Intent.ACTION_USER_INFO_CHANGED),
-                )
-            }
-
-            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
-        }
-
-    @Test
-    fun `System user unlocked broadcast - refresh users`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            val refreshUsersCallCount = userRepository.refreshUsersCallCount
-
-            fakeBroadcastDispatcher.registeredReceivers.forEach {
-                it.onReceive(
-                    context,
-                    Intent(Intent.ACTION_USER_UNLOCKED)
-                        .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM),
-                )
-            }
-
-            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
-        }
-
-    @Test
-    fun `Non-system user unlocked broadcast - do not refresh users`() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 2, includeGuest = false)
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            val refreshUsersCallCount = userRepository.refreshUsersCallCount
-
-            fakeBroadcastDispatcher.registeredReceivers.forEach {
-                it.onReceive(
-                    context,
-                    Intent(Intent.ACTION_USER_UNLOCKED).putExtra(Intent.EXTRA_USER_HANDLE, 1337),
-                )
-            }
-
-            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount)
-        }
-
-    @Test
-    fun userRecords() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = false)
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            keyguardRepository.setKeyguardShowing(false)
-
-            testCoroutineScope.advanceUntilIdle()
-
-            assertRecords(
-                records = underTest.userRecords.value,
-                userIds = listOf(0, 1, 2),
-                selectedUserIndex = 0,
-                includeGuest = false,
-                expectedActions =
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    ),
-            )
-        }
-
-    @Test
-    fun selectedUserRecord() =
-        runBlocking(IMMEDIATE) {
-            val userInfos = createUserInfos(count = 3, includeGuest = true)
-            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
-            userRepository.setUserInfos(userInfos)
-            userRepository.setSelectedUserInfo(userInfos[0])
-            keyguardRepository.setKeyguardShowing(false)
-
-            assertRecordForUser(
-                record = underTest.selectedUserRecord.value,
-                id = 0,
-                hasPicture = true,
-                isCurrent = true,
-                isSwitchToEnabled = true,
-            )
-        }
-
-    private fun assertUsers(
-        models: List<UserModel>?,
-        count: Int,
-        selectedIndex: Int = 0,
-        includeGuest: Boolean = false,
-    ) {
-        checkNotNull(models)
-        assertThat(models.size).isEqualTo(count)
-        models.forEachIndexed { index, model ->
-            assertUser(
-                model = model,
-                id = index,
-                isSelected = index == selectedIndex,
-                isGuest = includeGuest && index == count - 1
-            )
-        }
-    }
-
-    private fun assertUser(
-        model: UserModel?,
-        id: Int,
-        isSelected: Boolean = false,
-        isGuest: Boolean = false,
-    ) {
-        checkNotNull(model)
-        assertThat(model.id).isEqualTo(id)
-        assertThat(model.name).isEqualTo(Text.Loaded(if (isGuest) "guest" else "user_$id"))
-        assertThat(model.isSelected).isEqualTo(isSelected)
-        assertThat(model.isSelectable).isTrue()
-        assertThat(model.isGuest).isEqualTo(isGuest)
-    }
-
-    private fun assertRecords(
-        records: List<UserRecord>,
-        userIds: List<Int>,
-        selectedUserIndex: Int = 0,
-        includeGuest: Boolean = false,
-        expectedActions: List<UserActionModel> = emptyList(),
-    ) {
-        assertThat(records.size >= userIds.size).isTrue()
-        userIds.indices.forEach { userIndex ->
-            val record = records[userIndex]
-            assertThat(record.info).isNotNull()
-            val isGuest = includeGuest && userIndex == userIds.size - 1
-            assertRecordForUser(
-                record = record,
-                id = userIds[userIndex],
-                hasPicture = !isGuest,
-                isCurrent = userIndex == selectedUserIndex,
-                isGuest = isGuest,
-                isSwitchToEnabled = true,
-            )
-        }
-
-        assertThat(records.size - userIds.size).isEqualTo(expectedActions.size)
-        (userIds.size until userIds.size + expectedActions.size).forEach { actionIndex ->
-            val record = records[actionIndex]
-            assertThat(record.info).isNull()
-            assertRecordForAction(
-                record = record,
-                type = expectedActions[actionIndex - userIds.size],
-            )
-        }
-    }
-
-    private fun assertRecordForUser(
-        record: UserRecord?,
-        id: Int? = null,
-        hasPicture: Boolean = false,
-        isCurrent: Boolean = false,
-        isGuest: Boolean = false,
-        isSwitchToEnabled: Boolean = false,
-    ) {
-        checkNotNull(record)
-        assertThat(record.info?.id).isEqualTo(id)
-        assertThat(record.picture != null).isEqualTo(hasPicture)
-        assertThat(record.isCurrent).isEqualTo(isCurrent)
-        assertThat(record.isGuest).isEqualTo(isGuest)
-        assertThat(record.isSwitchToEnabled).isEqualTo(isSwitchToEnabled)
-    }
-
-    private fun assertRecordForAction(
-        record: UserRecord,
-        type: UserActionModel,
-    ) {
-        assertThat(record.isGuest).isEqualTo(type == UserActionModel.ENTER_GUEST_MODE)
-        assertThat(record.isAddUser).isEqualTo(type == UserActionModel.ADD_USER)
-        assertThat(record.isAddSupervisedUser)
-            .isEqualTo(type == UserActionModel.ADD_SUPERVISED_USER)
-    }
-
-    private fun createUserInfos(
-        count: Int,
-        includeGuest: Boolean,
-    ): List<UserInfo> {
-        return (0 until count).map { index ->
-            val isGuest = includeGuest && index == count - 1
-            createUserInfo(
-                id = index,
-                name =
-                    if (isGuest) {
-                        "guest"
-                    } else {
-                        "user_$index"
-                    },
-                isPrimary = !isGuest && index == 0,
-                isGuest = isGuest,
-            )
-        }
-    }
-
-    private fun createUserInfo(
-        id: Int,
-        name: String,
-        isPrimary: Boolean = false,
-        isGuest: Boolean = false,
-    ): UserInfo {
-        return UserInfo(
-            id,
-            name,
-            /* iconPath= */ "",
-            /* flags= */ if (isPrimary) {
-                UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN
-            } else {
-                0
-            },
-            if (isGuest) {
-                UserManager.USER_TYPE_FULL_GUEST
-            } else {
-                UserManager.USER_TYPE_FULL_SYSTEM
-            },
-        )
-    }
-
-    companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
-        private val ICON = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
-        private val GUEST_ICON: Drawable = mock()
-        private const val SUPERVISED_USER_CREATION_APP_PACKAGE = "supervisedUserCreation"
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index 58f5531..463f517 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -19,51 +19,90 @@
 
 import android.app.ActivityManager
 import android.app.admin.DevicePolicyManager
+import android.content.Intent
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
 import android.os.UserManager
+import android.provider.Settings
+import androidx.test.filters.SmallTest
+import com.android.internal.R.drawable.ic_account_circle
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.GuestResetOrExitSessionReceiver
 import com.android.systemui.GuestResumeSessionReceiver
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
+import com.android.systemui.common.shared.model.Text
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.user.UserSwitchDialogController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
+import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.user.data.source.UserRecord
+import com.android.systemui.user.domain.model.ShowDialogRequestModel
+import com.android.systemui.user.shared.model.UserActionModel
+import com.android.systemui.user.shared.model.UserModel
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.advanceUntilIdle
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
-abstract class UserInteractorTest : SysuiTestCase() {
+@SmallTest
+@RunWith(JUnit4::class)
+class UserInteractorTest : SysuiTestCase() {
 
-    @Mock protected lateinit var controller: UserSwitcherController
-    @Mock protected lateinit var activityStarter: ActivityStarter
-    @Mock protected lateinit var manager: UserManager
-    @Mock protected lateinit var activityManager: ActivityManager
-    @Mock protected lateinit var deviceProvisionedController: DeviceProvisionedController
-    @Mock protected lateinit var devicePolicyManager: DevicePolicyManager
-    @Mock protected lateinit var uiEventLogger: UiEventLogger
-    @Mock protected lateinit var dialogShower: UserSwitchDialogController.DialogShower
+    @Mock private lateinit var activityStarter: ActivityStarter
+    @Mock private lateinit var manager: UserManager
+    @Mock private lateinit var activityManager: ActivityManager
+    @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+    @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
 
-    protected lateinit var underTest: UserInteractor
+    private lateinit var underTest: UserInteractor
 
-    protected lateinit var testCoroutineScope: TestCoroutineScope
-    protected lateinit var userRepository: FakeUserRepository
-    protected lateinit var keyguardRepository: FakeKeyguardRepository
-    protected lateinit var telephonyRepository: FakeTelephonyRepository
+    private lateinit var testCoroutineScope: TestCoroutineScope
+    private lateinit var userRepository: FakeUserRepository
+    private lateinit var keyguardRepository: FakeKeyguardRepository
+    private lateinit var telephonyRepository: FakeTelephonyRepository
 
-    abstract fun isRefactored(): Boolean
-
-    open fun setUp() {
+    @Before
+    fun setUp() {
         MockitoAnnotations.initMocks(this)
+        whenever(manager.getUserIcon(anyInt())).thenReturn(ICON)
+        whenever(manager.canAddMoreUsers(any())).thenReturn(true)
+
+        overrideResource(R.drawable.ic_account_circle, GUEST_ICON)
+        overrideResource(R.dimen.max_avatar_size, 10)
+        overrideResource(
+            com.android.internal.R.string.config_supervisedUserCreationPackage,
+            SUPERVISED_USER_CREATION_APP_PACKAGE,
+        )
 
         userRepository = FakeUserRepository()
         keyguardRepository = FakeKeyguardRepository()
@@ -79,16 +118,11 @@
             UserInteractor(
                 applicationContext = context,
                 repository = userRepository,
-                controller = controller,
                 activityStarter = activityStarter,
                 keyguardInteractor =
                     KeyguardInteractor(
                         repository = keyguardRepository,
                     ),
-                featureFlags =
-                    FakeFeatureFlags().apply {
-                        set(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER, !isRefactored())
-                    },
                 manager = manager,
                 applicationScope = testCoroutineScope,
                 telephonyInteractor =
@@ -117,7 +151,708 @@
             )
     }
 
+    @Test
+    fun `onRecordSelected - user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(info = userInfos[1]), dialogShower)
+
+            verify(dialogShower).dismiss()
+            verify(activityManager).switchUser(userInfos[1].id)
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - switch to guest user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(info = userInfos.last()))
+
+            verify(activityManager).switchUser(userInfos.last().id)
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - enter guest mode`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true)
+            whenever(manager.createGuest(any())).thenReturn(guestUserInfo)
+
+            underTest.onRecordSelected(UserRecord(isGuest = true), dialogShower)
+
+            verify(dialogShower).dismiss()
+            verify(manager).createGuest(any())
+            Unit
+        }
+
+    @Test
+    fun `onRecordSelected - action`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            underTest.onRecordSelected(UserRecord(isAddSupervisedUser = true), dialogShower)
+
+            verify(dialogShower, never()).dismiss()
+            verify(activityStarter).startActivity(any(), anyBoolean())
+        }
+
+    @Test
+    fun `users - switcher enabled`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var value: List<UserModel>? = null
+            val job = underTest.users.onEach { value = it }.launchIn(this)
+            assertUsers(models = value, count = 3, includeGuest = true)
+
+            job.cancel()
+        }
+
+    @Test
+    fun `users - switches to second user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var value: List<UserModel>? = null
+            val job = underTest.users.onEach { value = it }.launchIn(this)
+            userRepository.setSelectedUserInfo(userInfos[1])
+
+            assertUsers(models = value, count = 2, selectedIndex = 1)
+            job.cancel()
+        }
+
+    @Test
+    fun `users - switcher not enabled`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = false))
+
+            var value: List<UserModel>? = null
+            val job = underTest.users.onEach { value = it }.launchIn(this)
+            assertUsers(models = value, count = 1)
+
+            job.cancel()
+        }
+
+    @Test
+    fun selectedUser() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var value: UserModel? = null
+            val job = underTest.selectedUser.onEach { value = it }.launchIn(this)
+            assertUser(value, id = 0, isSelected = true)
+
+            userRepository.setSelectedUserInfo(userInfos[1])
+            assertUser(value, id = 1, isSelected = true)
+
+            job.cancel()
+        }
+
+    @Test
+    fun `actions - device unlocked`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            keyguardRepository.setKeyguardShowing(false)
+            var value: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { value = it }.launchIn(this)
+
+            assertThat(value)
+                .isEqualTo(
+                    listOf(
+                        UserActionModel.ENTER_GUEST_MODE,
+                        UserActionModel.ADD_USER,
+                        UserActionModel.ADD_SUPERVISED_USER,
+                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
+                    )
+                )
+
+            job.cancel()
+        }
+
+    @Test
+    fun `actions - device unlocked user not primary - empty list`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[1])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            keyguardRepository.setKeyguardShowing(false)
+            var value: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { value = it }.launchIn(this)
+
+            assertThat(value).isEqualTo(emptyList<UserActionModel>())
+
+            job.cancel()
+        }
+
+    @Test
+    fun `actions - device unlocked user is guest - empty list`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = true)
+            assertThat(userInfos[1].isGuest).isTrue()
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[1])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            keyguardRepository.setKeyguardShowing(false)
+            var value: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { value = it }.launchIn(this)
+
+            assertThat(value).isEqualTo(emptyList<UserActionModel>())
+
+            job.cancel()
+        }
+
+    @Test
+    fun `actions - device locked add from lockscreen set - full list`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(
+                UserSwitcherSettingsModel(
+                    isUserSwitcherEnabled = true,
+                    isAddUsersFromLockscreen = true,
+                )
+            )
+            keyguardRepository.setKeyguardShowing(false)
+            var value: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { value = it }.launchIn(this)
+
+            assertThat(value)
+                .isEqualTo(
+                    listOf(
+                        UserActionModel.ENTER_GUEST_MODE,
+                        UserActionModel.ADD_USER,
+                        UserActionModel.ADD_SUPERVISED_USER,
+                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
+                    )
+                )
+
+            job.cancel()
+        }
+
+    @Test
+    fun `actions - device locked - only guest action and manage user is shown`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            keyguardRepository.setKeyguardShowing(true)
+            var value: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { value = it }.launchIn(this)
+
+            assertThat(value)
+                .isEqualTo(
+                    listOf(
+                        UserActionModel.ENTER_GUEST_MODE,
+                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
+                    )
+                )
+
+            job.cancel()
+        }
+
+    @Test
+    fun `executeAction - add user - dialog shown`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            keyguardRepository.setKeyguardShowing(false)
+            var dialogRequest: ShowDialogRequestModel? = null
+            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
+            val dialogShower: UserSwitchDialogController.DialogShower = mock()
+
+            underTest.executeAction(UserActionModel.ADD_USER, dialogShower)
+            assertThat(dialogRequest)
+                .isEqualTo(
+                    ShowDialogRequestModel.ShowAddUserDialog(
+                        userHandle = userInfos[0].userHandle,
+                        isKeyguardShowing = false,
+                        showEphemeralMessage = false,
+                        dialogShower = dialogShower,
+                    )
+                )
+
+            underTest.onDialogShown()
+            assertThat(dialogRequest).isNull()
+
+            job.cancel()
+        }
+
+    @Test
+    fun `executeAction - add supervised user - starts activity`() =
+        runBlocking(IMMEDIATE) {
+            underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
+
+            val intentCaptor = kotlinArgumentCaptor<Intent>()
+            verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
+            assertThat(intentCaptor.value.action)
+                .isEqualTo(UserManager.ACTION_CREATE_SUPERVISED_USER)
+            assertThat(intentCaptor.value.`package`).isEqualTo(SUPERVISED_USER_CREATION_APP_PACKAGE)
+        }
+
+    @Test
+    fun `executeAction - navigate to manage users`() =
+        runBlocking(IMMEDIATE) {
+            underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
+
+            val intentCaptor = kotlinArgumentCaptor<Intent>()
+            verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
+            assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
+        }
+
+    @Test
+    fun `executeAction - guest mode`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            val guestUserInfo = createUserInfo(id = 1337, name = "guest", isGuest = true)
+            whenever(manager.createGuest(any())).thenReturn(guestUserInfo)
+            val dialogRequests = mutableListOf<ShowDialogRequestModel?>()
+            val showDialogsJob =
+                underTest.dialogShowRequests
+                    .onEach {
+                        dialogRequests.add(it)
+                        if (it != null) {
+                            underTest.onDialogShown()
+                        }
+                    }
+                    .launchIn(this)
+            val dismissDialogsJob =
+                underTest.dialogDismissRequests
+                    .onEach {
+                        if (it != null) {
+                            underTest.onDialogDismissed()
+                        }
+                    }
+                    .launchIn(this)
+
+            underTest.executeAction(UserActionModel.ENTER_GUEST_MODE)
+
+            assertThat(dialogRequests)
+                .contains(
+                    ShowDialogRequestModel.ShowUserCreationDialog(isGuest = true),
+                )
+            verify(activityManager).switchUser(guestUserInfo.id)
+
+            showDialogsJob.cancel()
+            dismissDialogsJob.cancel()
+        }
+
+    @Test
+    fun `selectUser - already selected guest re-selected - exit guest dialog`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = true)
+            val guestUserInfo = userInfos[1]
+            assertThat(guestUserInfo.isGuest).isTrue()
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(guestUserInfo)
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            var dialogRequest: ShowDialogRequestModel? = null
+            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
+
+            underTest.selectUser(
+                newlySelectedUserId = guestUserInfo.id,
+                dialogShower = dialogShower,
+            )
+
+            assertThat(dialogRequest)
+                .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
+            verify(dialogShower, never()).dismiss()
+            job.cancel()
+        }
+
+    @Test
+    fun `selectUser - currently guest non-guest selected - exit guest dialog`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = true)
+            val guestUserInfo = userInfos[1]
+            assertThat(guestUserInfo.isGuest).isTrue()
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(guestUserInfo)
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            var dialogRequest: ShowDialogRequestModel? = null
+            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
+
+            underTest.selectUser(newlySelectedUserId = userInfos[0].id, dialogShower = dialogShower)
+
+            assertThat(dialogRequest)
+                .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
+            verify(dialogShower, never()).dismiss()
+            job.cancel()
+        }
+
+    @Test
+    fun `selectUser - not currently guest - switches users`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            var dialogRequest: ShowDialogRequestModel? = null
+            val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
+
+            underTest.selectUser(newlySelectedUserId = userInfos[1].id, dialogShower = dialogShower)
+
+            assertThat(dialogRequest).isNull()
+            verify(activityManager).switchUser(userInfos[1].id)
+            verify(dialogShower).dismiss()
+            job.cancel()
+        }
+
+    @Test
+    fun `Telephony call state changes - refreshes users`() =
+        runBlocking(IMMEDIATE) {
+            val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+            telephonyRepository.setCallState(1)
+
+            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
+        }
+
+    @Test
+    fun `User switched broadcast`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            val callback1: UserInteractor.UserCallback = mock()
+            val callback2: UserInteractor.UserCallback = mock()
+            underTest.addCallback(callback1)
+            underTest.addCallback(callback2)
+            val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+            userRepository.setSelectedUserInfo(userInfos[1])
+            fakeBroadcastDispatcher.registeredReceivers.forEach {
+                it.onReceive(
+                    context,
+                    Intent(Intent.ACTION_USER_SWITCHED)
+                        .putExtra(Intent.EXTRA_USER_HANDLE, userInfos[1].id),
+                )
+            }
+
+            verify(callback1).onUserStateChanged()
+            verify(callback2).onUserStateChanged()
+            assertThat(userRepository.secondaryUserId).isEqualTo(userInfos[1].id)
+            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
+        }
+
+    @Test
+    fun `User info changed broadcast`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+            fakeBroadcastDispatcher.registeredReceivers.forEach {
+                it.onReceive(
+                    context,
+                    Intent(Intent.ACTION_USER_INFO_CHANGED),
+                )
+            }
+
+            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
+        }
+
+    @Test
+    fun `System user unlocked broadcast - refresh users`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+            fakeBroadcastDispatcher.registeredReceivers.forEach {
+                it.onReceive(
+                    context,
+                    Intent(Intent.ACTION_USER_UNLOCKED)
+                        .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM),
+                )
+            }
+
+            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
+        }
+
+    @Test
+    fun `Non-system user unlocked broadcast - do not refresh users`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 2, includeGuest = false)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+            fakeBroadcastDispatcher.registeredReceivers.forEach {
+                it.onReceive(
+                    context,
+                    Intent(Intent.ACTION_USER_UNLOCKED).putExtra(Intent.EXTRA_USER_HANDLE, 1337),
+                )
+            }
+
+            assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount)
+        }
+
+    @Test
+    fun userRecords() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = false)
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            keyguardRepository.setKeyguardShowing(false)
+
+            testCoroutineScope.advanceUntilIdle()
+
+            assertRecords(
+                records = underTest.userRecords.value,
+                userIds = listOf(0, 1, 2),
+                selectedUserIndex = 0,
+                includeGuest = false,
+                expectedActions =
+                    listOf(
+                        UserActionModel.ENTER_GUEST_MODE,
+                        UserActionModel.ADD_USER,
+                        UserActionModel.ADD_SUPERVISED_USER,
+                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
+                    ),
+            )
+        }
+
+    @Test
+    fun selectedUserRecord() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[0])
+            keyguardRepository.setKeyguardShowing(false)
+
+            assertRecordForUser(
+                record = underTest.selectedUserRecord.value,
+                id = 0,
+                hasPicture = true,
+                isCurrent = true,
+                isSwitchToEnabled = true,
+            )
+        }
+
+    @Test
+    fun `users - secondary user - no guest user`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[1])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var res: List<UserModel>? = null
+            val job = underTest.users.onEach { res = it }.launchIn(this)
+            assertThat(res?.size == 2).isTrue()
+            assertThat(res?.find { it.isGuest }).isNull()
+            job.cancel()
+        }
+
+    @Test
+    fun `users - secondary user - no guest action`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[1])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var res: List<UserActionModel>? = null
+            val job = underTest.actions.onEach { res = it }.launchIn(this)
+            assertThat(res?.find { it == UserActionModel.ENTER_GUEST_MODE }).isNull()
+            job.cancel()
+        }
+
+    @Test
+    fun `users - secondary user - no guest user record`() =
+        runBlocking(IMMEDIATE) {
+            val userInfos = createUserInfos(count = 3, includeGuest = true)
+            userRepository.setUserInfos(userInfos)
+            userRepository.setSelectedUserInfo(userInfos[1])
+            userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
+
+            var res: List<UserRecord>? = null
+            val job = underTest.userRecords.onEach { res = it }.launchIn(this)
+            assertThat(res?.find { it.isGuest }).isNull()
+            job.cancel()
+        }
+
+    private fun assertUsers(
+        models: List<UserModel>?,
+        count: Int,
+        selectedIndex: Int = 0,
+        includeGuest: Boolean = false,
+    ) {
+        checkNotNull(models)
+        assertThat(models.size).isEqualTo(count)
+        models.forEachIndexed { index, model ->
+            assertUser(
+                model = model,
+                id = index,
+                isSelected = index == selectedIndex,
+                isGuest = includeGuest && index == count - 1
+            )
+        }
+    }
+
+    private fun assertUser(
+        model: UserModel?,
+        id: Int,
+        isSelected: Boolean = false,
+        isGuest: Boolean = false,
+    ) {
+        checkNotNull(model)
+        assertThat(model.id).isEqualTo(id)
+        assertThat(model.name).isEqualTo(Text.Loaded(if (isGuest) "guest" else "user_$id"))
+        assertThat(model.isSelected).isEqualTo(isSelected)
+        assertThat(model.isSelectable).isTrue()
+        assertThat(model.isGuest).isEqualTo(isGuest)
+    }
+
+    private fun assertRecords(
+        records: List<UserRecord>,
+        userIds: List<Int>,
+        selectedUserIndex: Int = 0,
+        includeGuest: Boolean = false,
+        expectedActions: List<UserActionModel> = emptyList(),
+    ) {
+        assertThat(records.size >= userIds.size).isTrue()
+        userIds.indices.forEach { userIndex ->
+            val record = records[userIndex]
+            assertThat(record.info).isNotNull()
+            val isGuest = includeGuest && userIndex == userIds.size - 1
+            assertRecordForUser(
+                record = record,
+                id = userIds[userIndex],
+                hasPicture = !isGuest,
+                isCurrent = userIndex == selectedUserIndex,
+                isGuest = isGuest,
+                isSwitchToEnabled = true,
+            )
+        }
+
+        assertThat(records.size - userIds.size).isEqualTo(expectedActions.size)
+        (userIds.size until userIds.size + expectedActions.size).forEach { actionIndex ->
+            val record = records[actionIndex]
+            assertThat(record.info).isNull()
+            assertRecordForAction(
+                record = record,
+                type = expectedActions[actionIndex - userIds.size],
+            )
+        }
+    }
+
+    private fun assertRecordForUser(
+        record: UserRecord?,
+        id: Int? = null,
+        hasPicture: Boolean = false,
+        isCurrent: Boolean = false,
+        isGuest: Boolean = false,
+        isSwitchToEnabled: Boolean = false,
+    ) {
+        checkNotNull(record)
+        assertThat(record.info?.id).isEqualTo(id)
+        assertThat(record.picture != null).isEqualTo(hasPicture)
+        assertThat(record.isCurrent).isEqualTo(isCurrent)
+        assertThat(record.isGuest).isEqualTo(isGuest)
+        assertThat(record.isSwitchToEnabled).isEqualTo(isSwitchToEnabled)
+    }
+
+    private fun assertRecordForAction(
+        record: UserRecord,
+        type: UserActionModel,
+    ) {
+        assertThat(record.isGuest).isEqualTo(type == UserActionModel.ENTER_GUEST_MODE)
+        assertThat(record.isAddUser).isEqualTo(type == UserActionModel.ADD_USER)
+        assertThat(record.isAddSupervisedUser)
+            .isEqualTo(type == UserActionModel.ADD_SUPERVISED_USER)
+    }
+
+    private fun createUserInfos(
+        count: Int,
+        includeGuest: Boolean,
+    ): List<UserInfo> {
+        return (0 until count).map { index ->
+            val isGuest = includeGuest && index == count - 1
+            createUserInfo(
+                id = index,
+                name =
+                    if (isGuest) {
+                        "guest"
+                    } else {
+                        "user_$index"
+                    },
+                isPrimary = !isGuest && index == 0,
+                isGuest = isGuest,
+            )
+        }
+    }
+
+    private fun createUserInfo(
+        id: Int,
+        name: String,
+        isPrimary: Boolean = false,
+        isGuest: Boolean = false,
+    ): UserInfo {
+        return UserInfo(
+            id,
+            name,
+            /* iconPath= */ "",
+            /* flags= */ if (isPrimary) {
+                UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN
+            } else {
+                0
+            },
+            if (isGuest) {
+                UserManager.USER_TYPE_FULL_GUEST
+            } else {
+                UserManager.USER_TYPE_FULL_SYSTEM
+            },
+        )
+    }
+
     companion object {
         private val IMMEDIATE = Dispatchers.Main.immediate
+        private val ICON = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+        private val GUEST_ICON: Drawable = mock()
+        private const val SUPERVISED_USER_CREATION_APP_PACKAGE = "supervisedUserCreation"
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorUnrefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorUnrefactoredTest.kt
deleted file mode 100644
index 6a17c8d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorUnrefactoredTest.kt
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.user.domain.interactor
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.nullable
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.verify
-
-@SmallTest
-@RunWith(JUnit4::class)
-open class UserInteractorUnrefactoredTest : UserInteractorTest() {
-
-    override fun isRefactored(): Boolean {
-        return false
-    }
-
-    @Before
-    override fun setUp() {
-        super.setUp()
-    }
-
-    @Test
-    fun `actions - not actionable when locked and locked - no actions`() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setActions(UserActionModel.values().toList())
-            userRepository.setActionableWhenLocked(false)
-            keyguardRepository.setKeyguardShowing(true)
-
-            var actions: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { actions = it }.launchIn(this)
-
-            assertThat(actions).isEmpty()
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - not actionable when locked and not locked`() =
-        runBlocking(IMMEDIATE) {
-            setActions()
-            userRepository.setActionableWhenLocked(false)
-            keyguardRepository.setKeyguardShowing(false)
-
-            var actions: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { actions = it }.launchIn(this)
-
-            assertThat(actions)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    )
-                )
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - actionable when locked and not locked`() =
-        runBlocking(IMMEDIATE) {
-            setActions()
-            userRepository.setActionableWhenLocked(true)
-            keyguardRepository.setKeyguardShowing(false)
-
-            var actions: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { actions = it }.launchIn(this)
-
-            assertThat(actions)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    )
-                )
-            job.cancel()
-        }
-
-    @Test
-    fun `actions - actionable when locked and locked`() =
-        runBlocking(IMMEDIATE) {
-            setActions()
-            userRepository.setActionableWhenLocked(true)
-            keyguardRepository.setKeyguardShowing(true)
-
-            var actions: List<UserActionModel>? = null
-            val job = underTest.actions.onEach { actions = it }.launchIn(this)
-
-            assertThat(actions)
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE,
-                        UserActionModel.ADD_USER,
-                        UserActionModel.ADD_SUPERVISED_USER,
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
-                    )
-                )
-            job.cancel()
-        }
-
-    @Test
-    fun selectUser() {
-        val userId = 3
-
-        underTest.selectUser(userId)
-
-        verify(controller).onUserSelected(eq(userId), nullable())
-    }
-
-    @Test
-    fun `executeAction - guest`() {
-        underTest.executeAction(UserActionModel.ENTER_GUEST_MODE)
-
-        verify(controller).createAndSwitchToGuestUser(nullable())
-    }
-
-    @Test
-    fun `executeAction - add user`() {
-        underTest.executeAction(UserActionModel.ADD_USER)
-
-        verify(controller).showAddUserDialog(nullable())
-    }
-
-    @Test
-    fun `executeAction - add supervised user`() {
-        underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
-
-        verify(controller).startSupervisedUserActivity()
-    }
-
-    @Test
-    fun `executeAction - manage users`() {
-        underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
-
-        verify(activityStarter).startActivity(any(), anyBoolean())
-    }
-
-    private fun setActions() {
-        userRepository.setActions(UserActionModel.values().toList())
-    }
-
-    companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 116023a..db13680 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -19,7 +19,7 @@
 
 import android.app.ActivityManager
 import android.app.admin.DevicePolicyManager
-import android.graphics.drawable.Drawable
+import android.content.pm.UserInfo
 import android.os.UserManager
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
@@ -27,32 +27,37 @@
 import com.android.systemui.GuestResumeSessionReceiver
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.Text
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.power.data.repository.FakePowerRepository
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.UserSwitcherController
 import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
+import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.user.domain.interactor.GuestUserInteractor
 import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
 import com.android.systemui.user.domain.interactor.UserInteractor
 import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
 import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.user.shared.model.UserModel
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.TestCoroutineScope
-import kotlinx.coroutines.yield
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestResult
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -60,11 +65,11 @@
 import org.mockito.Mock
 import org.mockito.MockitoAnnotations
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(JUnit4::class)
 class UserSwitcherViewModelTest : SysuiTestCase() {
 
-    @Mock private lateinit var controller: UserSwitcherController
     @Mock private lateinit var activityStarter: ActivityStarter
     @Mock private lateinit var activityManager: ActivityManager
     @Mock private lateinit var manager: UserManager
@@ -80,28 +85,47 @@
     private lateinit var keyguardRepository: FakeKeyguardRepository
     private lateinit var powerRepository: FakePowerRepository
 
+    private lateinit var testDispatcher: TestDispatcher
+    private lateinit var testScope: TestScope
+    private lateinit var injectedScope: CoroutineScope
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        whenever(manager.canAddMoreUsers(any())).thenReturn(true)
+        whenever(manager.getUserSwitchability(any()))
+            .thenReturn(UserManager.SWITCHABILITY_STATUS_OK)
+        overrideResource(
+            com.android.internal.R.string.config_supervisedUserCreationPackage,
+            SUPERVISED_USER_CREATION_PACKAGE,
+        )
 
+        testDispatcher = UnconfinedTestDispatcher()
+        testScope = TestScope(testDispatcher)
+        injectedScope = CoroutineScope(testScope.coroutineContext + SupervisorJob())
         userRepository = FakeUserRepository()
+        runBlocking {
+            userRepository.setSettings(
+                UserSwitcherSettingsModel(
+                    isUserSwitcherEnabled = true,
+                )
+            )
+        }
+
         keyguardRepository = FakeKeyguardRepository()
         powerRepository = FakePowerRepository()
-        val featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.USER_INTERACTOR_AND_REPO_USE_CONTROLLER, true)
-        val scope = TestCoroutineScope()
         val refreshUsersScheduler =
             RefreshUsersScheduler(
-                applicationScope = scope,
-                mainDispatcher = IMMEDIATE,
+                applicationScope = injectedScope,
+                mainDispatcher = testDispatcher,
                 repository = userRepository,
             )
         val guestUserInteractor =
             GuestUserInteractor(
                 applicationContext = context,
-                applicationScope = scope,
-                mainDispatcher = IMMEDIATE,
-                backgroundDispatcher = IMMEDIATE,
+                applicationScope = injectedScope,
+                mainDispatcher = testDispatcher,
+                backgroundDispatcher = testDispatcher,
                 manager = manager,
                 repository = userRepository,
                 deviceProvisionedController = deviceProvisionedController,
@@ -118,21 +142,19 @@
                         UserInteractor(
                             applicationContext = context,
                             repository = userRepository,
-                            controller = controller,
                             activityStarter = activityStarter,
                             keyguardInteractor =
                                 KeyguardInteractor(
                                     repository = keyguardRepository,
                                 ),
-                            featureFlags = featureFlags,
                             manager = manager,
-                            applicationScope = scope,
+                            applicationScope = injectedScope,
                             telephonyInteractor =
                                 TelephonyInteractor(
                                     repository = FakeTelephonyRepository(),
                                 ),
                             broadcastDispatcher = fakeBroadcastDispatcher,
-                            backgroundDispatcher = IMMEDIATE,
+                            backgroundDispatcher = testDispatcher,
                             activityManager = activityManager,
                             refreshUsersScheduler = refreshUsersScheduler,
                             guestUserInteractor = guestUserInteractor,
@@ -141,222 +163,216 @@
                         PowerInteractor(
                             repository = powerRepository,
                         ),
-                    featureFlags = featureFlags,
                     guestUserInteractor = guestUserInteractor,
                 )
                 .create(UserSwitcherViewModel::class.java)
     }
 
     @Test
-    fun users() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setUsers(
+    fun users() = selfCancelingTest {
+        val userInfos =
+            listOf(
+                UserInfo(
+                    /* id= */ 0,
+                    /* name= */ "zero",
+                    /* iconPath= */ "",
+                    /* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN,
+                    UserManager.USER_TYPE_FULL_SYSTEM,
+                ),
+                UserInfo(
+                    /* id= */ 1,
+                    /* name= */ "one",
+                    /* iconPath= */ "",
+                    /* flags= */ 0,
+                    UserManager.USER_TYPE_FULL_SYSTEM,
+                ),
+                UserInfo(
+                    /* id= */ 2,
+                    /* name= */ "two",
+                    /* iconPath= */ "",
+                    /* flags= */ 0,
+                    UserManager.USER_TYPE_FULL_SYSTEM,
+                ),
+            )
+        userRepository.setUserInfos(userInfos)
+        userRepository.setSelectedUserInfo(userInfos[0])
+
+        val userViewModels = mutableListOf<List<UserViewModel>>()
+        val job = launch(testDispatcher) { underTest.users.toList(userViewModels) }
+
+        assertThat(userViewModels.last()).hasSize(3)
+        assertUserViewModel(
+            viewModel = userViewModels.last()[0],
+            viewKey = 0,
+            name = "zero",
+            isSelectionMarkerVisible = true,
+        )
+        assertUserViewModel(
+            viewModel = userViewModels.last()[1],
+            viewKey = 1,
+            name = "one",
+            isSelectionMarkerVisible = false,
+        )
+        assertUserViewModel(
+            viewModel = userViewModels.last()[2],
+            viewKey = 2,
+            name = "two",
+            isSelectionMarkerVisible = false,
+        )
+        job.cancel()
+    }
+
+    @Test
+    fun `maximumUserColumns - few users`() = selfCancelingTest {
+        setUsers(count = 2)
+        val values = mutableListOf<Int>()
+        val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
+
+        assertThat(values.last()).isEqualTo(4)
+
+        job.cancel()
+    }
+
+    @Test
+    fun `maximumUserColumns - many users`() = selfCancelingTest {
+        setUsers(count = 5)
+        val values = mutableListOf<Int>()
+        val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
+
+        assertThat(values.last()).isEqualTo(3)
+        job.cancel()
+    }
+
+    @Test
+    fun `isOpenMenuButtonVisible - has actions - true`() = selfCancelingTest {
+        setUsers(2)
+
+        val isVisible = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isOpenMenuButtonVisible.toList(isVisible) }
+
+        assertThat(isVisible.last()).isTrue()
+        job.cancel()
+    }
+
+    @Test
+    fun `isOpenMenuButtonVisible - no actions - false`() = selfCancelingTest {
+        val userInfos = setUsers(2)
+        userRepository.setSelectedUserInfo(userInfos[1])
+        keyguardRepository.setKeyguardShowing(true)
+        whenever(manager.canAddMoreUsers(any())).thenReturn(false)
+
+        val isVisible = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isOpenMenuButtonVisible.toList(isVisible) }
+
+        assertThat(isVisible.last()).isFalse()
+        job.cancel()
+    }
+
+    @Test
+    fun menu() = selfCancelingTest {
+        val isMenuVisible = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isMenuVisible.toList(isMenuVisible) }
+        assertThat(isMenuVisible.last()).isFalse()
+
+        underTest.onOpenMenuButtonClicked()
+        assertThat(isMenuVisible.last()).isTrue()
+
+        underTest.onMenuClosed()
+        assertThat(isMenuVisible.last()).isFalse()
+
+        job.cancel()
+    }
+
+    @Test
+    fun `menu actions`() = selfCancelingTest {
+        setUsers(2)
+        val actions = mutableListOf<List<UserActionViewModel>>()
+        val job = launch(testDispatcher) { underTest.menu.toList(actions) }
+
+        assertThat(actions.last().map { it.viewKey })
+            .isEqualTo(
                 listOf(
-                    UserModel(
-                        id = 0,
-                        name = Text.Loaded("zero"),
-                        image = USER_IMAGE,
-                        isSelected = true,
-                        isSelectable = true,
-                        isGuest = false,
-                    ),
-                    UserModel(
-                        id = 1,
-                        name = Text.Loaded("one"),
-                        image = USER_IMAGE,
-                        isSelected = false,
-                        isSelectable = true,
-                        isGuest = false,
-                    ),
-                    UserModel(
-                        id = 2,
-                        name = Text.Loaded("two"),
-                        image = USER_IMAGE,
-                        isSelected = false,
-                        isSelectable = false,
-                        isGuest = false,
-                    ),
+                    UserActionModel.ENTER_GUEST_MODE.ordinal.toLong(),
+                    UserActionModel.ADD_USER.ordinal.toLong(),
+                    UserActionModel.ADD_SUPERVISED_USER.ordinal.toLong(),
+                    UserActionModel.NAVIGATE_TO_USER_MANAGEMENT.ordinal.toLong(),
                 )
             )
 
-            var userViewModels: List<UserViewModel>? = null
-            val job = underTest.users.onEach { userViewModels = it }.launchIn(this)
-
-            assertThat(userViewModels).hasSize(3)
-            assertUserViewModel(
-                viewModel = userViewModels?.get(0),
-                viewKey = 0,
-                name = "zero",
-                isSelectionMarkerVisible = true,
-                alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA,
-                isClickable = true,
-            )
-            assertUserViewModel(
-                viewModel = userViewModels?.get(1),
-                viewKey = 1,
-                name = "one",
-                isSelectionMarkerVisible = false,
-                alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA,
-                isClickable = true,
-            )
-            assertUserViewModel(
-                viewModel = userViewModels?.get(2),
-                viewKey = 2,
-                name = "two",
-                isSelectionMarkerVisible = false,
-                alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA,
-                isClickable = false,
-            )
-            job.cancel()
-        }
+        job.cancel()
+    }
 
     @Test
-    fun `maximumUserColumns - few users`() =
-        runBlocking(IMMEDIATE) {
-            setUsers(count = 2)
-            var value: Int? = null
-            val job = underTest.maximumUserColumns.onEach { value = it }.launchIn(this)
+    fun `isFinishRequested - finishes when user is switched`() = selfCancelingTest {
+        val userInfos = setUsers(count = 2)
+        val isFinishRequested = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
+        assertThat(isFinishRequested.last()).isFalse()
 
-            assertThat(value).isEqualTo(4)
-            job.cancel()
-        }
+        userRepository.setSelectedUserInfo(userInfos[1])
+
+        assertThat(isFinishRequested.last()).isTrue()
+
+        job.cancel()
+    }
 
     @Test
-    fun `maximumUserColumns - many users`() =
-        runBlocking(IMMEDIATE) {
-            setUsers(count = 5)
-            var value: Int? = null
-            val job = underTest.maximumUserColumns.onEach { value = it }.launchIn(this)
+    fun `isFinishRequested - finishes when the screen turns off`() = selfCancelingTest {
+        setUsers(count = 2)
+        powerRepository.setInteractive(true)
+        val isFinishRequested = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
+        assertThat(isFinishRequested.last()).isFalse()
 
-            assertThat(value).isEqualTo(3)
-            job.cancel()
-        }
+        powerRepository.setInteractive(false)
+
+        assertThat(isFinishRequested.last()).isTrue()
+
+        job.cancel()
+    }
 
     @Test
-    fun `isOpenMenuButtonVisible - has actions - true`() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setActions(UserActionModel.values().toList())
+    fun `isFinishRequested - finishes when cancel button is clicked`() = selfCancelingTest {
+        setUsers(count = 2)
+        powerRepository.setInteractive(true)
+        val isFinishRequested = mutableListOf<Boolean>()
+        val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
+        assertThat(isFinishRequested.last()).isFalse()
 
-            var isVisible: Boolean? = null
-            val job = underTest.isOpenMenuButtonVisible.onEach { isVisible = it }.launchIn(this)
+        underTest.onCancelButtonClicked()
 
-            assertThat(isVisible).isTrue()
-            job.cancel()
-        }
+        assertThat(isFinishRequested.last()).isTrue()
 
-    @Test
-    fun `isOpenMenuButtonVisible - no actions - false`() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setActions(emptyList())
+        underTest.onFinished()
 
-            var isVisible: Boolean? = null
-            val job = underTest.isOpenMenuButtonVisible.onEach { isVisible = it }.launchIn(this)
+        assertThat(isFinishRequested.last()).isFalse()
 
-            assertThat(isVisible).isFalse()
-            job.cancel()
-        }
+        job.cancel()
+    }
 
-    @Test
-    fun menu() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setActions(UserActionModel.values().toList())
-            var isMenuVisible: Boolean? = null
-            val job = underTest.isMenuVisible.onEach { isMenuVisible = it }.launchIn(this)
-            assertThat(isMenuVisible).isFalse()
-
-            underTest.onOpenMenuButtonClicked()
-            assertThat(isMenuVisible).isTrue()
-
-            underTest.onMenuClosed()
-            assertThat(isMenuVisible).isFalse()
-
-            job.cancel()
-        }
-
-    @Test
-    fun `menu actions`() =
-        runBlocking(IMMEDIATE) {
-            userRepository.setActions(UserActionModel.values().toList())
-            var actions: List<UserActionViewModel>? = null
-            val job = underTest.menu.onEach { actions = it }.launchIn(this)
-
-            assertThat(actions?.map { it.viewKey })
-                .isEqualTo(
-                    listOf(
-                        UserActionModel.ENTER_GUEST_MODE.ordinal.toLong(),
-                        UserActionModel.ADD_USER.ordinal.toLong(),
-                        UserActionModel.ADD_SUPERVISED_USER.ordinal.toLong(),
-                        UserActionModel.NAVIGATE_TO_USER_MANAGEMENT.ordinal.toLong(),
-                    )
-                )
-
-            job.cancel()
-        }
-
-    @Test
-    fun `isFinishRequested - finishes when user is switched`() =
-        runBlocking(IMMEDIATE) {
-            setUsers(count = 2)
-            var isFinishRequested: Boolean? = null
-            val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this)
-            assertThat(isFinishRequested).isFalse()
-
-            userRepository.setSelectedUser(1)
-            yield()
-            assertThat(isFinishRequested).isTrue()
-
-            job.cancel()
-        }
-
-    @Test
-    fun `isFinishRequested - finishes when the screen turns off`() =
-        runBlocking(IMMEDIATE) {
-            setUsers(count = 2)
-            powerRepository.setInteractive(true)
-            var isFinishRequested: Boolean? = null
-            val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this)
-            assertThat(isFinishRequested).isFalse()
-
-            powerRepository.setInteractive(false)
-            yield()
-            assertThat(isFinishRequested).isTrue()
-
-            job.cancel()
-        }
-
-    @Test
-    fun `isFinishRequested - finishes when cancel button is clicked`() =
-        runBlocking(IMMEDIATE) {
-            setUsers(count = 2)
-            powerRepository.setInteractive(true)
-            var isFinishRequested: Boolean? = null
-            val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this)
-            assertThat(isFinishRequested).isFalse()
-
-            underTest.onCancelButtonClicked()
-            yield()
-            assertThat(isFinishRequested).isTrue()
-
-            underTest.onFinished()
-            yield()
-            assertThat(isFinishRequested).isFalse()
-
-            job.cancel()
-        }
-
-    private suspend fun setUsers(count: Int) {
-        userRepository.setUsers(
+    private suspend fun setUsers(count: Int): List<UserInfo> {
+        val userInfos =
             (0 until count).map { index ->
-                UserModel(
-                    id = index,
-                    name = Text.Loaded("$index"),
-                    image = USER_IMAGE,
-                    isSelected = index == 0,
-                    isSelectable = true,
-                    isGuest = false,
+                UserInfo(
+                    /* id= */ index,
+                    /* name= */ "$index",
+                    /* iconPath= */ "",
+                    /* flags= */ if (index == 0) {
+                        // This is the primary user.
+                        UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN
+                    } else {
+                        // This isn't the primary user.
+                        0
+                    },
+                    UserManager.USER_TYPE_FULL_SYSTEM,
                 )
             }
-        )
+        userRepository.setUserInfos(userInfos)
+
+        if (userInfos.isNotEmpty()) {
+            userRepository.setSelectedUserInfo(userInfos[0])
+        }
+        return userInfos
     }
 
     private fun assertUserViewModel(
@@ -364,19 +380,25 @@
         viewKey: Int,
         name: String,
         isSelectionMarkerVisible: Boolean,
-        alpha: Float,
-        isClickable: Boolean,
     ) {
         checkNotNull(viewModel)
         assertThat(viewModel.viewKey).isEqualTo(viewKey)
         assertThat(viewModel.name).isEqualTo(Text.Loaded(name))
         assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible)
-        assertThat(viewModel.alpha).isEqualTo(alpha)
-        assertThat(viewModel.onClicked != null).isEqualTo(isClickable)
+        assertThat(viewModel.alpha)
+            .isEqualTo(LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA)
+        assertThat(viewModel.onClicked).isNotNull()
     }
 
+    private fun selfCancelingTest(
+        block: suspend TestScope.() -> Unit,
+    ): TestResult =
+        testScope.runTest {
+            block()
+            injectedScope.coroutineContext[Job.Key]?.cancelAndJoin()
+        }
+
     companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
-        private val USER_IMAGE = mock<Drawable>()
+        private const val SUPERVISED_USER_CREATION_PACKAGE = "com.some.package"
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 6f70f0e..a798f40 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -44,6 +44,9 @@
     private val _isDozing = MutableStateFlow(false)
     override val isDozing: Flow<Boolean> = _isDozing
 
+    private val _isDreaming = MutableStateFlow(false)
+    override val isDreaming: Flow<Boolean> = _isDreaming
+
     private val _dozeAmount = MutableStateFlow(0f)
     override val dozeAmount: Flow<Float> = _dozeAmount
 
@@ -54,10 +57,13 @@
     override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState
 
     private val _isUdfpsSupported = MutableStateFlow(false)
-    
+
     private val _isBouncerShowing = MutableStateFlow(false)
     override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing
 
+    private val _isKeyguardGoingAway = MutableStateFlow(false)
+    override val isKeyguardGoingAway: Flow<Boolean> = _isKeyguardGoingAway
+
     private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
     override val biometricUnlockState: Flow<BiometricUnlockModel> = _biometricUnlockState
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index 4df8aa4..b7c8cbf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -20,26 +20,15 @@
 import android.content.pm.UserInfo
 import android.os.UserHandle
 import com.android.systemui.user.data.model.UserSwitcherSettingsModel
-import com.android.systemui.user.shared.model.UserActionModel
-import com.android.systemui.user.shared.model.UserModel
 import java.util.concurrent.atomic.AtomicBoolean
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.yield
 
 class FakeUserRepository : UserRepository {
 
-    private val _users = MutableStateFlow<List<UserModel>>(emptyList())
-    override val users: Flow<List<UserModel>> = _users.asStateFlow()
-    override val selectedUser: Flow<UserModel> =
-        users.map { models -> models.first { model -> model.isSelected } }
-
-    private val _actions = MutableStateFlow<List<UserActionModel>>(emptyList())
-    override val actions: Flow<List<UserActionModel>> = _actions.asStateFlow()
-
     private val _userSwitcherSettings = MutableStateFlow(UserSwitcherSettingsModel())
     override val userSwitcherSettings: Flow<UserSwitcherSettingsModel> =
         _userSwitcherSettings.asStateFlow()
@@ -52,9 +41,6 @@
 
     override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
 
-    private val _isActionableWhenLocked = MutableStateFlow(false)
-    override val isActionableWhenLocked: Flow<Boolean> = _isActionableWhenLocked.asStateFlow()
-
     private var _isGuestUserAutoCreated: Boolean = false
     override val isGuestUserAutoCreated: Boolean
         get() = _isGuestUserAutoCreated
@@ -100,35 +86,6 @@
         yield()
     }
 
-    fun setUsers(models: List<UserModel>) {
-        _users.value = models
-    }
-
-    suspend fun setSelectedUser(userId: Int) {
-        check(_users.value.find { it.id == userId } != null) {
-            "Cannot select a user with ID $userId - no user with that ID found!"
-        }
-
-        setUsers(
-            _users.value.map { model ->
-                when {
-                    model.isSelected && model.id != userId -> model.copy(isSelected = false)
-                    !model.isSelected && model.id == userId -> model.copy(isSelected = true)
-                    else -> model
-                }
-            }
-        )
-        yield()
-    }
-
-    fun setActions(models: List<UserActionModel>) {
-        _actions.value = models
-    }
-
-    fun setActionableWhenLocked(value: Boolean) {
-        _isActionableWhenLocked.value = value
-    }
-
     fun setGuestUserAutoCreated(value: Boolean) {
         _isGuestUserAutoCreated = value
     }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
index 92435d0..9ffb314 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
@@ -113,7 +113,7 @@
         info.minWidth = parser.getAttributeInt(null, ATTR_MIN_WIDTH, 0);
         info.minHeight = parser.getAttributeInt(null, ATTR_MIN_HEIGHT, 0);
         info.minResizeWidth = parser.getAttributeInt(null, ATTR_MIN_RESIZE_WIDTH, 0);
-        info.minResizeWidth = parser.getAttributeInt(null, ATTR_MIN_RESIZE_HEIGHT, 0);
+        info.minResizeHeight = parser.getAttributeInt(null, ATTR_MIN_RESIZE_HEIGHT, 0);
         info.maxResizeWidth = parser.getAttributeInt(null, ATTR_MAX_RESIZE_WIDTH, 0);
         info.maxResizeHeight = parser.getAttributeInt(null, ATTR_MAX_RESIZE_HEIGHT, 0);
         info.targetCellWidth = parser.getAttributeInt(null, ATTR_TARGET_CELL_WIDTH, 0);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c128b5e..4f1efd6 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -528,7 +528,7 @@
     private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
             List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
         if (!packageExistsForUser(packageName, accounts.userId)) {
-            Log.d(TAG, "Package not found " + packageName);
+            Log.w(TAG, "getAccountsAndVisibilityForPackage#Package not found " + packageName);
             return new LinkedHashMap<>();
         }
 
@@ -677,7 +677,7 @@
                 restoreCallingIdentity(identityToken);
             }
         } catch (NameNotFoundException e) {
-            Log.d(TAG, "Package not found " + e.getMessage());
+            Log.w(TAG, "resolveAccountVisibility#Package not found " + e.getMessage());
             return AccountManager.VISIBILITY_NOT_VISIBLE;
         }
 
@@ -756,7 +756,7 @@
             }
             return true;
         } catch (NameNotFoundException e) {
-            Log.d(TAG, "Package not found " + e.getMessage());
+            Log.w(TAG, "isPreOApplication#Package not found " + e.getMessage());
             return true;
         }
     }
@@ -4063,7 +4063,7 @@
             int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
             return hasAccountAccess(account, packageName, uid);
         } catch (NameNotFoundException e) {
-            Log.d(TAG, "Package not found " + e.getMessage());
+            Log.w(TAG, "hasAccountAccess#Package not found " + e.getMessage());
             return false;
         }
     }
@@ -4195,7 +4195,7 @@
         }
         final long token = Binder.clearCallingIdentity();
         try {
-            AccountAndUser[] allAccounts = getAllAccounts();
+            AccountAndUser[] allAccounts = getAllAccountsForSystemProcess();
             for (int i = allAccounts.length - 1; i >= 0; i--) {
                 if (allAccounts[i].account.equals(account)) {
                     return true;
@@ -4345,10 +4345,11 @@
     /**
      * Returns accounts for all running users, ignores visibility values.
      *
+     * Should only be called by System process.
      * @hide
      */
     @NonNull
-    public AccountAndUser[] getRunningAccounts() {
+    public AccountAndUser[] getRunningAccountsForSystem() {
         final int[] runningUserIds;
         try {
             runningUserIds = ActivityManager.getService().getRunningUserIds();
@@ -4356,26 +4357,34 @@
             // Running in system_server; should never happen
             throw new RuntimeException(e);
         }
-        return getAccounts(runningUserIds);
+        return getAccountsForSystem(runningUserIds);
     }
 
     /**
      * Returns accounts for all users, ignores visibility values.
      *
+     * Should only be called by system process
+     *
      * @hide
      */
     @NonNull
-    public AccountAndUser[] getAllAccounts() {
+    public AccountAndUser[] getAllAccountsForSystemProcess() {
         final List<UserInfo> users = getUserManager().getAliveUsers();
         final int[] userIds = new int[users.size()];
         for (int i = 0; i < userIds.length; i++) {
             userIds[i] = users.get(i).id;
         }
-        return getAccounts(userIds);
+        return getAccountsForSystem(userIds);
     }
 
+    /**
+     * Returns all accounts for the given user, ignores all visibility checks.
+     * This should only be called by system process.
+     *
+     * @hide
+     */
     @NonNull
-    private AccountAndUser[] getAccounts(int[] userIds) {
+    private AccountAndUser[] getAccountsForSystem(int[] userIds) {
         final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
         for (int userId : userIds) {
             UserAccounts userAccounts = getUserAccounts(userId);
@@ -4384,7 +4393,7 @@
                     userAccounts,
                     null /* type */,
                     Binder.getCallingUid(),
-                    null /* packageName */,
+                    "android"/* packageName */,
                     false /* include managed not visible*/);
             for (Account account : accounts) {
                 runningAccounts.add(new AccountAndUser(account, userId));
@@ -5355,7 +5364,7 @@
             }
         } else {
             Account[] accounts = getAccountsFromCache(userAccounts, null /* type */,
-                    Process.SYSTEM_UID, null /* packageName */, false);
+                    Process.SYSTEM_UID, "android" /* packageName */, false);
             fout.println("Accounts: " + accounts.length);
             for (Account account : accounts) {
                 fout.println("  " + account.toString());
@@ -5550,7 +5559,7 @@
                         return true;
                     }
                 } catch (PackageManager.NameNotFoundException e) {
-                    Log.d(TAG, "Package not found " + e.getMessage());
+                    Log.w(TAG, "isPrivileged#Package not found " + e.getMessage());
                 }
             }
         } finally {
@@ -6074,7 +6083,7 @@
                     }
                 }
             } catch (NameNotFoundException e) {
-                Log.d(TAG, "Package not found " + e.getMessage());
+                Log.w(TAG, "filterSharedAccounts#Package not found " + e.getMessage());
             }
             Map<Account, Integer> filtered = new LinkedHashMap<>();
             for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index c372096..3016228 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -246,6 +246,18 @@
     private static final String KEY_MAX_PHANTOM_PROCESSES = "max_phantom_processes";
 
     /**
+     * Enables proactive killing of cached apps
+     */
+    private static final String KEY_PROACTIVE_KILLS_ENABLED = "proactive_kills_enabled";
+
+    /**
+      * Trim LRU cached app when swap falls below this minimum percentage.
+      *
+      * Depends on KEY_PROACTIVE_KILLS_ENABLED
+      */
+    private static final String KEY_LOW_SWAP_THRESHOLD_PERCENT = "low_swap_threshold_percent";
+
+    /**
      * Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
      * Settings.Global. This allows it to be set experimentally unless it has been
      * enabled/disabled in developer options. Defaults to false.
@@ -833,6 +845,10 @@
      */
     private static final long DEFAULT_MIN_ASSOC_LOG_DURATION = 5 * 60 * 1000; // 5 mins
 
+    private static final boolean DEFAULT_PROACTIVE_KILLS_ENABLED = false;
+
+    private static final float DEFAULT_LOW_SWAP_THRESHOLD_PERCENT = 0.10f;
+
     private static final String KEY_MIN_ASSOC_LOG_DURATION = "min_assoc_log_duration";
 
     public static long MIN_ASSOC_LOG_DURATION = DEFAULT_MIN_ASSOC_LOG_DURATION;
@@ -863,6 +879,8 @@
     public static boolean BINDER_HEAVY_HITTER_AUTO_SAMPLER_ENABLED;
     public static int BINDER_HEAVY_HITTER_AUTO_SAMPLER_BATCHSIZE;
     public static float BINDER_HEAVY_HITTER_AUTO_SAMPLER_THRESHOLD;
+    public static boolean PROACTIVE_KILLS_ENABLED = DEFAULT_PROACTIVE_KILLS_ENABLED;
+    public static float LOW_SWAP_THRESHOLD_PERCENT = DEFAULT_LOW_SWAP_THRESHOLD_PERCENT;
 
     private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
             new OnPropertiesChangedListener() {
@@ -990,6 +1008,12 @@
                             case KEY_NETWORK_ACCESS_TIMEOUT_MS:
                                 updateNetworkAccessTimeoutMs();
                                 break;
+                            case KEY_PROACTIVE_KILLS_ENABLED:
+                                updateProactiveKillsEnabled();
+                                break;
+                            case KEY_LOW_SWAP_THRESHOLD_PERCENT:
+                                updateLowSwapThresholdPercent();
+                                break;
                             default:
                                 break;
                         }
@@ -1592,6 +1616,20 @@
         CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3;
     }
 
+    private void updateProactiveKillsEnabled() {
+        PROACTIVE_KILLS_ENABLED = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_PROACTIVE_KILLS_ENABLED,
+                DEFAULT_PROACTIVE_KILLS_ENABLED);
+    }
+
+    private void updateLowSwapThresholdPercent() {
+        LOW_SWAP_THRESHOLD_PERCENT = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_LOW_SWAP_THRESHOLD_PERCENT,
+                DEFAULT_LOW_SWAP_THRESHOLD_PERCENT);
+    }
+
     private void updateMinAssocLogDuration() {
         MIN_ASSOC_LOG_DURATION = DeviceConfig.getLong(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MIN_ASSOC_LOG_DURATION,
@@ -1779,6 +1817,10 @@
         pw.print("="); pw.println(mServiceBindAlmostPerceptibleTimeoutMs);
         pw.print("  "); pw.print(KEY_NETWORK_ACCESS_TIMEOUT_MS);
         pw.print("="); pw.println(mNetworkAccessTimeoutMs);
+        pw.print("  "); pw.print(KEY_PROACTIVE_KILLS_ENABLED);
+        pw.print("="); pw.println(PROACTIVE_KILLS_ENABLED);
+        pw.print("  "); pw.print(KEY_LOW_SWAP_THRESHOLD_PERCENT);
+        pw.print("="); pw.println(LOW_SWAP_THRESHOLD_PERCENT);
 
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 9921956..cee9f79 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -651,7 +651,7 @@
     /**
      * Retrieves the free swap percentage.
      */
-    static private native double getFreeSwapPercent();
+    static native double getFreeSwapPercent();
 
     /**
      * Reads the flag value from DeviceConfig to determine whether app compaction
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index bc939d6..441506d 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1034,6 +1034,12 @@
 
     private long mNextNoKillDebugMessageTime;
 
+    private double mLastFreeSwapPercent = 1.00;
+
+    private static double getFreeSwapPercent() {
+        return CachedAppOptimizer.getFreeSwapPercent();
+    }
+
     @GuardedBy({"mService", "mProcLock"})
     private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
             final long oldTime, final ActiveUids activeUids, String oomAdjReason) {
@@ -1058,6 +1064,11 @@
         int numEmpty = 0;
         int numTrimming = 0;
 
+        boolean proactiveKillsEnabled = mConstants.PROACTIVE_KILLS_ENABLED;
+        double lowSwapThresholdPercent = mConstants.LOW_SWAP_THRESHOLD_PERCENT;
+        double freeSwapPercent =  proactiveKillsEnabled ? getFreeSwapPercent() : 1.00;
+        ProcessRecord lruCachedApp = null;
+
         for (int i = numLru - 1; i >= 0; i--) {
             ProcessRecord app = lruList.get(i);
             final ProcessStateRecord state = app.mState;
@@ -1095,6 +1106,8 @@
                                     ApplicationExitInfo.REASON_OTHER,
                                     ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
                                     true);
+                        } else if (proactiveKillsEnabled) {
+                            lruCachedApp = app;
                         }
                         break;
                     case PROCESS_STATE_CACHED_EMPTY:
@@ -1114,6 +1127,8 @@
                                         ApplicationExitInfo.REASON_OTHER,
                                         ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
                                         true);
+                            } else if (proactiveKillsEnabled) {
+                                lruCachedApp = app;
                             }
                         }
                         break;
@@ -1145,6 +1160,20 @@
             }
         }
 
+        if (proactiveKillsEnabled                               // Proactive kills enabled?
+                && doKillExcessiveProcesses                     // Should kill excessive processes?
+                && freeSwapPercent < lowSwapThresholdPercent    // Swap below threshold?
+                && lruCachedApp != null                         // If no cached app, let LMKD decide
+                // If swap is non-decreasing, give reclaim a chance to catch up
+                && freeSwapPercent < mLastFreeSwapPercent) {
+            lruCachedApp.killLocked("swap low and too many cached",
+                    ApplicationExitInfo.REASON_OTHER,
+                    ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
+                    true);
+        }
+
+        mLastFreeSwapPercent = freeSwapPercent;
+
         return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3eac406..9700e56 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2207,16 +2207,25 @@
             Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;
             boolean bindMountAppStorageDirs = false;
             boolean bindMountAppsData = mAppDataIsolationEnabled
-                    && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
+                    && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid)
+                        || app.isSdkSandbox)
                     && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
 
             // Get all packages belongs to the same shared uid. sharedPackages is empty array
             // if it doesn't have shared uid.
             final PackageManagerInternal pmInt = mService.getPackageManagerInternal();
-            final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
-                    app.info.packageName, app.userId);
-            final String[] targetPackagesList = sharedPackages.length == 0
-                    ? new String[]{app.info.packageName} : sharedPackages;
+
+            // In the case of sdk sandbox, the pkgDataInfoMap of only the client app associated with
+            // the sandbox is required to handle app visibility restrictions for the sandbox.
+            final String[] targetPackagesList;
+            if (app.isSdkSandbox) {
+                targetPackagesList = new String[]{app.sdkSandboxClientAppPackage};
+            } else {
+                final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+                        app.info.packageName, app.userId);
+                targetPackagesList = sharedPackages.length == 0
+                        ? new String[]{app.info.packageName} : sharedPackages;
+            }
 
             final boolean hasAppStorage = hasAppStorage(pmInt, app.info.packageName);
 
@@ -2242,7 +2251,7 @@
                 bindMountAppsData = false;
             }
 
-            if (!hasAppStorage) {
+            if (!hasAppStorage && !app.isSdkSandbox) {
                 bindMountAppsData = false;
                 pkgDataInfoMap = null;
                 allowlistedAppDataInfoMap = null;
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 4a9ac77..17cd5d1 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -86,6 +86,7 @@
         DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS,
         DeviceConfig.NAMESPACE_LMKD_NATIVE,
         DeviceConfig.NAMESPACE_MEDIA_NATIVE,
+        DeviceConfig.NAMESPACE_MGLRU_NATIVE,
         DeviceConfig.NAMESPACE_NETD_NATIVE,
         DeviceConfig.NAMESPACE_NNAPI_NATIVE,
         DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 4013ace..3584f16 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -1276,20 +1276,12 @@
 
     void onUserSwitching(TargetUser from, TargetUser to) {
         final int toUserId = to.getUserIdentifier();
-        if (from != null) {
-            synchronized (mLock) {
-                final int fromUserId = from.getUserIdentifier();
-                if (mSettings.containsKey(fromUserId)) {
-                    final Message msg = mHandler.obtainMessage(REMOVE_SETTINGS);
-                    msg.obj = fromUserId;
-                    mHandler.sendMessage(msg);
-                }
-            }
-        }
+        // we want to re-populate the setting when switching user as the device config may have
+        // changed, which will only update for the previous user, see
+        // DeviceConfigListener#onPropertiesChanged.
         final Message msg = mHandler.obtainMessage(POPULATE_GAME_MODE_SETTINGS);
         msg.obj = toUserId;
         mHandler.sendMessage(msg);
-
         if (mGameServiceController != null) {
             mGameServiceController.notifyNewForegroundUser(to);
         }
@@ -1429,9 +1421,10 @@
                 Slog.v(TAG, "Package configuration not found for " + packageName);
                 return;
             }
+        } else {
+            updateFps(packageConfig, packageName, gameMode, userId);
+            updateCompatModeDownscale(packageConfig, packageName, gameMode);
         }
-        updateCompatModeDownscale(packageConfig, packageName, gameMode);
-        updateFps(packageConfig, packageName, gameMode, userId);
         updateUseAngle(packageName, gameMode);
     }
 
diff --git a/services/core/java/com/android/server/biometrics/log/ALSProbe.java b/services/core/java/com/android/server/biometrics/log/ALSProbe.java
index da43618..d584c99 100644
--- a/services/core/java/com/android/server/biometrics/log/ALSProbe.java
+++ b/services/core/java/com/android/server/biometrics/log/ALSProbe.java
@@ -120,7 +120,7 @@
 
         // if a final consumer is set it will call destroy/disable on the next value if requested
         if (!mDestroyed && mNextConsumer == null) {
-            disableLightSensorLoggingLocked();
+            disableLightSensorLoggingLocked(false /* destroying */);
         }
     }
 
@@ -130,7 +130,7 @@
 
         // if a final consumer is set it will call destroy/disable on the next value if requested
         if (!mDestroyed && mNextConsumer == null) {
-            disableLightSensorLoggingLocked();
+            disableLightSensorLoggingLocked(true /* destroying */);
             mDestroyed = true;
         }
     }
@@ -177,11 +177,10 @@
         final float current = mLastAmbientLux;
         if (current > -1f) {
             nextConsumer.consume(current);
-        } else if (mDestroyed) {
-            nextConsumer.consume(-1f);
         } else if (mNextConsumer != null) {
             mNextConsumer.add(nextConsumer);
         } else {
+            mDestroyed = false;
             mNextConsumer = nextConsumer;
             enableLightSensorLoggingLocked();
         }
@@ -199,12 +198,14 @@
         resetTimerLocked(true /* start */);
     }
 
-    private void disableLightSensorLoggingLocked() {
+    private void disableLightSensorLoggingLocked(boolean destroying) {
         resetTimerLocked(false /* start */);
 
         if (mEnabled) {
             mEnabled = false;
-            mLastAmbientLux = -1;
+            if (!destroying) {
+                mLastAmbientLux = -1;
+            }
             mSensorManager.unregisterListener(mLightSensorListener);
             Slog.v(TAG, "Disable ALS: " + mLightSensorListener.hashCode());
         }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 73afa60..eb81e70 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2215,7 +2215,8 @@
         pw.print("Storage low: "); pw.println(storageLowIntent != null);
         pw.print("Clock valid: "); pw.println(mSyncStorageEngine.isClockValid());
 
-        final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();
+        final AccountAndUser[] accounts =
+                AccountManagerService.getSingleton().getAllAccountsForSystemProcess();
 
         pw.print("Accounts: ");
         if (accounts != INITIAL_ACCOUNTS_ARRAY) {
@@ -3274,7 +3275,8 @@
         private void updateRunningAccountsH(EndPoint syncTargets) {
             synchronized (mAccountsLock) {
                 AccountAndUser[] oldAccounts = mRunningAccounts;
-                mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts();
+                mRunningAccounts =
+                        AccountManagerService.getSingleton().getRunningAccountsForSystem();
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
                     Slog.v(TAG, "Accounts list: ");
                     for (AccountAndUser acc : mRunningAccounts) {
@@ -3316,7 +3318,8 @@
             }
 
             // Cancel all jobs from non-existent accounts.
-            AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
+            AccountAndUser[] allAccounts =
+                    AccountManagerService.getSingleton().getAllAccountsForSystemProcess();
             List<SyncOperation> ops = getAllPendingSyncs();
             for (int i = 0, opsSize = ops.size(); i < opsSize; i++) {
                 SyncOperation op = ops.get(i);
diff --git a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
index d74c702..7c9a484 100644
--- a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
+++ b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
@@ -27,6 +27,7 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -287,6 +288,14 @@
                     localDate)) {
                 return lastBrightnessStats;
             } else {
+                // It is a new day, and we have available data, so log data. The daily boundary
+                // might not be right if the user changes timezones but that is fine, since it
+                // won't be that frequent.
+                if (lastBrightnessStats != null) {
+                    FrameworkStatsLog.write(FrameworkStatsLog.AMBIENT_BRIGHTNESS_STATS_REPORTED,
+                            lastBrightnessStats.getStats(),
+                            lastBrightnessStats.getBucketBoundaries());
+                }
                 AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(localDate,
                         BUCKET_BOUNDARIES_FOR_NEW_STATS);
                 if (userStats.size() == MAX_DAYS_TO_TRACK) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 7806ece..1b20e6a 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -123,6 +123,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.AnimationThread;
 import com.android.server.DisplayThread;
@@ -146,6 +147,7 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
 
+
 /**
  * Manages attached displays.
  * <p>
@@ -1681,7 +1683,20 @@
         final Point userPreferredResolution =
                 mPersistentDataStore.getUserPreferredResolution(device);
         final float refreshRate = mPersistentDataStore.getUserPreferredRefreshRate(device);
-        if (userPreferredResolution == null && Float.isNaN(refreshRate)) {
+        // If value in persistentDataStore is null, preserving the mode from systemPreferredMode.
+        // This is required because in some devices, user-preferred mode was not stored in
+        // persistentDataStore, but was stored in a config which is returned through
+        // systemPreferredMode.
+        if ((userPreferredResolution == null && Float.isNaN(refreshRate))
+                || (userPreferredResolution.equals(0, 0) && refreshRate == 0.0f)) {
+            Display.Mode systemPreferredMode = device.getSystemPreferredDisplayModeLocked();
+            if (systemPreferredMode == null) {
+                return;
+            }
+            storeModeInPersistentDataStoreLocked(
+                    display.getDisplayIdLocked(), systemPreferredMode.getPhysicalWidth(),
+                    systemPreferredMode.getPhysicalHeight(), systemPreferredMode.getRefreshRate());
+            device.setUserPreferredDisplayModeLocked(systemPreferredMode);
             return;
         }
         Display.Mode.Builder modeBuilder = new Display.Mode.Builder();
@@ -1867,6 +1882,15 @@
                 if (displayDevice == null) {
                     return;
                 }
+                if (mLogicalDisplayMapper.getDisplayLocked(displayDevice) != null
+                        && mLogicalDisplayMapper.getDisplayLocked(displayDevice)
+                        .getDisplayInfoLocked().type == Display.TYPE_INTERNAL && c != null) {
+                    FrameworkStatsLog.write(FrameworkStatsLog.BRIGHTNESS_CONFIGURATION_UPDATED,
+                                c.getCurve().first,
+                                c.getCurve().second,
+                                // should not be logged for virtual displays
+                                uniqueId);
+                }
                 mPersistentDataStore.setBrightnessConfigurationForDisplayLocked(c, displayDevice,
                         userSerial, packageName);
             } finally {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 69c890d..36bff20 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2810,18 +2810,22 @@
 
         float appliedPowerFactor = event.isLowPowerModeSet() ? event.powerFactor : -1f;
 
-        FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
-                convertToNits(event.initialBrightness),
-                convertToNits(event.brightness),
-                event.slowAmbientLux,
-                event.physicalDisplayId,
-                event.isShortTermModelActive(),
-                appliedPowerFactor,
-                appliedRbcStrength,
-                appliedHbmMaxNits,
-                appliedThermalCapNits,
-                event.automaticBrightnessEnabled,
-                FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
+        if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
+                && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
+                    .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
+            FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
+                    convertToNits(event.initialBrightness),
+                    convertToNits(event.brightness),
+                    event.slowAmbientLux,
+                    event.physicalDisplayId,
+                    event.isShortTermModelActive(),
+                    appliedPowerFactor,
+                    appliedRbcStrength,
+                    appliedHbmMaxNits,
+                    appliedThermalCapNits,
+                    event.automaticBrightnessEnabled,
+                    FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
+        }
     }
 
     class BrightnessEvent {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 2a21928..efb2cb7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -411,11 +411,8 @@
 
             // For a new display, we need to initialize the default mode ID.
             if (mDefaultModeId == INVALID_MODE_ID) {
-                mDefaultModeId = mSystemPreferredModeId != INVALID_MODE_ID
-                        ? mSystemPreferredModeId : activeRecord.mMode.getModeId();
-                mDefaultModeGroup = mSystemPreferredModeId != INVALID_MODE_ID
-                        ? preferredSfDisplayMode.group
-                        : mActiveSfDisplayMode.group;
+                mDefaultModeId = activeRecord.mMode.getModeId();
+                mDefaultModeGroup = mActiveSfDisplayMode.group;
             } else if (modesAdded && activeModeChanged) {
                 Slog.d(TAG, "New display modes are added and the active mode has changed, "
                         + "use active mode as default mode.");
@@ -897,6 +894,13 @@
         public void setUserPreferredDisplayModeLocked(Display.Mode mode) {
             final int oldModeId = getPreferredModeId();
             mUserPreferredMode = mode;
+            // When clearing the user preferred mode we need to also reset the default mode. This is
+            // used by DisplayModeDirector to determine the default resolution, so if we don't clear
+            // it then the resolution won't reset to what it would've been prior to setting a user
+            // preferred display mode.
+            if (mode == null && mSystemPreferredModeId != INVALID_MODE_ID) {
+                mDefaultModeId = mSystemPreferredModeId;
+            }
             if (mode != null && (mode.isRefreshRateSet() || mode.isResolutionSet())) {
                 Display.Mode matchingSupportedMode;
                 matchingSupportedMode = findMode(mode.getPhysicalWidth(),
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index f64006c..70c9e23 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -167,12 +167,6 @@
     LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
             @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
             @NonNull Handler handler) {
-        this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap());
-    }
-
-    LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
-            @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
-            @NonNull Handler handler, DeviceStateToLayoutMap deviceStateToLayoutMap) {
         mSyncRoot = syncRoot;
         mPowerManager = context.getSystemService(PowerManager.class);
         mInteractive = mPowerManager.isInteractive();
@@ -187,7 +181,7 @@
         mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
                 com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
         mDisplayDeviceRepo.addListener(this);
-        mDeviceStateToLayoutMap = deviceStateToLayoutMap;
+        mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
     }
 
     @Override
@@ -375,7 +369,9 @@
         // the transition is smooth. Plus, on some devices, only one internal displays can be
         // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be
         // temporarily turned off.
-        resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
+        if (mDeviceState != DeviceStateManager.INVALID_DEVICE_STATE) {
+            resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
+        }
         mPendingDeviceState = state;
         final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
                 mInteractive, mBootCompleted);
@@ -895,8 +891,8 @@
                 newDisplay.swapDisplaysLocked(oldDisplay);
             }
 
-            if (displayLayout.isEnabled()) {
-                setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_ENABLED);
+            if (!displayLayout.isEnabled()) {
+                setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_DISABLED);
             }
         }
 
@@ -916,7 +912,7 @@
         final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
         display.updateLocked(mDisplayDeviceRepo);
         mLogicalDisplays.put(displayId, display);
-        setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_DISABLED);
+        setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);
         return display;
     }
 
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index b9511c4..8f6df0f 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -116,7 +116,7 @@
     private final DreamUiEventLogger mDreamUiEventLogger;
     private final ComponentName mAmbientDisplayComponent;
     private final boolean mDismissDreamOnActivityStart;
-    private final boolean mDreamsOnlyEnabledForSystemUser;
+    private final boolean mDreamsOnlyEnabledForDockUser;
     private final boolean mDreamsEnabledByDefaultConfig;
     private final boolean mDreamsActivatedOnChargeByDefault;
     private final boolean mDreamsActivatedOnDockByDefault;
@@ -214,8 +214,8 @@
                 mContext.getResources().getStringArray(R.array.config_loggable_dream_prefixes));
         AmbientDisplayConfiguration adc = new AmbientDisplayConfiguration(mContext);
         mAmbientDisplayComponent = ComponentName.unflattenFromString(adc.ambientDisplayComponent());
-        mDreamsOnlyEnabledForSystemUser =
-                mContext.getResources().getBoolean(R.bool.config_dreamsOnlyEnabledForSystemUser);
+        mDreamsOnlyEnabledForDockUser =
+                mContext.getResources().getBoolean(R.bool.config_dreamsOnlyEnabledForDockUser);
         mDismissDreamOnActivityStart = mContext.getResources().getBoolean(
                 R.bool.config_dismissDreamOnActivityStart);
 
@@ -292,10 +292,9 @@
             pw.println();
             pw.println("mCurrentDream=" + mCurrentDream);
             pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
-            pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
+            pw.println("mDreamsOnlyEnabledForDockUser=" + mDreamsOnlyEnabledForDockUser);
             pw.println("mDreamsEnabledSetting=" + mDreamsEnabledSetting);
             pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
-            pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
             pw.println("mDreamsActivatedOnDockByDefault=" + mDreamsActivatedOnDockByDefault);
             pw.println("mDreamsActivatedOnChargeByDefault=" + mDreamsActivatedOnChargeByDefault);
             pw.println("mIsDocked=" + mIsDocked);
@@ -602,7 +601,8 @@
     }
 
     private boolean dreamsEnabledForUser(int userId) {
-        return !mDreamsOnlyEnabledForSystemUser || (userId == UserHandle.USER_SYSTEM);
+        // TODO(b/257333623): Support non-system Dock Users in HSUM.
+        return !mDreamsOnlyEnabledForDockUser || (userId == UserHandle.USER_SYSTEM);
     }
 
     private ServiceInfo getServiceInfo(ComponentName name) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 91d5698..89e0d05 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,6 +18,8 @@
 
 import static android.view.KeyEvent.KEYCODE_UNKNOWN;
 
+import android.Manifest;
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
@@ -2678,6 +2680,13 @@
         mNative.cancelCurrentTouch();
     }
 
+    @EnforcePermission(Manifest.permission.MONITOR_INPUT)
+    @Override
+    public void pilferPointers(IBinder inputChannelToken) {
+        Objects.requireNonNull(inputChannelToken);
+        mNative.pilferPointers(inputChannelToken);
+    }
+
     @Override
     public void registerBatteryListener(int deviceId, IInputDeviceBatteryListener listener) {
         Objects.requireNonNull(listener);
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index e27cbea..350aa6b 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -58,6 +58,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
 
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -87,6 +89,7 @@
     private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND_SERVICE;
 
     private final Context mContext;
+    private final UserManagerInternal mUserManagerInternal;
     private final Object mLock = new Object();
     final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
     final ActivityManager mActivityManager;
@@ -99,7 +102,7 @@
     @GuardedBy("mLock")
     private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
     @GuardedBy("mLock")
-    private int mCurrentUserId = -1;
+    private int mCurrentActiveUserId = -1;
 
     private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener =
             (uid, importance) -> {
@@ -125,12 +128,13 @@
         }
     };
 
-    MediaRouter2ServiceImpl(Context context) {
+    /* package */ MediaRouter2ServiceImpl(Context context) {
         mContext = context;
         mActivityManager = mContext.getSystemService(ActivityManager.class);
         mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener,
                 PACKAGE_IMPORTANCE_FOR_DISCOVERY);
         mPowerManager = mContext.getSystemService(PowerManager.class);
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
 
         IntentFilter screenOnOffIntentFilter = new IntentFilter();
         screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON);
@@ -601,25 +605,23 @@
         }
     }
 
-    //TODO(b/136703681): Review this is handling multi-user properly.
-    void switchUser() {
+    /* package */ void updateRunningUserAndProfiles(int newActiveUserId) {
         synchronized (mLock) {
-            int userId = ActivityManager.getCurrentUser();
-            if (mCurrentUserId != userId) {
-                final int oldUserId = mCurrentUserId;
-                mCurrentUserId = userId; // do this first
-
-                UserRecord oldUser = mUserRecords.get(oldUserId);
-                if (oldUser != null) {
-                    oldUser.mHandler.sendMessage(
-                            obtainMessage(UserHandler::stop, oldUser.mHandler));
-                    disposeUserIfNeededLocked(oldUser); // since no longer current user
-                }
-
-                UserRecord newUser = mUserRecords.get(userId);
-                if (newUser != null) {
-                    newUser.mHandler.sendMessage(
-                            obtainMessage(UserHandler::start, newUser.mHandler));
+            if (mCurrentActiveUserId != newActiveUserId) {
+                mCurrentActiveUserId = newActiveUserId;
+                for (int i = 0; i < mUserRecords.size(); i++) {
+                    int userId = mUserRecords.keyAt(i);
+                    UserRecord userRecord = mUserRecords.valueAt(i);
+                    if (isUserActiveLocked(userId)) {
+                        // userId corresponds to the active user, or one of its profiles. We
+                        // ensure the associated structures are initialized.
+                        userRecord.mHandler.sendMessage(
+                                obtainMessage(UserHandler::start, userRecord.mHandler));
+                    } else {
+                        userRecord.mHandler.sendMessage(
+                                obtainMessage(UserHandler::stop, userRecord.mHandler));
+                        disposeUserIfNeededLocked(userRecord);
+                    }
                 }
             }
         }
@@ -637,11 +639,21 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile
+     * of the active user, returns {@code false} otherwise.
+     */
+    @GuardedBy("mLock")
+    private boolean isUserActiveLocked(int userId) {
+        return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId;
+    }
+
     ////////////////////////////////////////////////////////////////
     ////  ***Locked methods related to MediaRouter2
     ////   - Should have @NonNull/@Nullable on all arguments
     ////////////////////////////////////////////////////////////////
 
+    @GuardedBy("mLock")
     private void registerRouter2Locked(@NonNull IMediaRouter2 router, int uid, int pid,
             @NonNull String packageName, int userId, boolean hasConfigureWifiDisplayPermission,
             boolean hasModifyAudioRoutingPermission) {
@@ -669,6 +681,7 @@
                         userRecord.mHandler, routerRecord));
     }
 
+    @GuardedBy("mLock")
     private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) {
         RouterRecord routerRecord = mAllRouterRecords.remove(router.asBinder());
         if (routerRecord == null) {
@@ -891,6 +904,7 @@
         return sessionInfos;
     }
 
+    @GuardedBy("mLock")
     private void registerManagerLocked(@NonNull IMediaRouter2Manager manager,
             int uid, int pid, @NonNull String packageName, int userId) {
         final IBinder binder = manager.asBinder();
@@ -1125,13 +1139,14 @@
     ////   - Should have @NonNull/@Nullable on all arguments
     ////////////////////////////////////////////////////////////
 
+    @GuardedBy("mLock")
     private UserRecord getOrCreateUserRecordLocked(int userId) {
         UserRecord userRecord = mUserRecords.get(userId);
         if (userRecord == null) {
             userRecord = new UserRecord(userId);
             mUserRecords.put(userId, userRecord);
             userRecord.init();
-            if (userId == mCurrentUserId) {
+            if (isUserActiveLocked(userId)) {
                 userRecord.mHandler.sendMessage(
                         obtainMessage(UserHandler::start, userRecord.mHandler));
             }
@@ -1139,12 +1154,13 @@
         return userRecord;
     }
 
+    @GuardedBy("mLock")
     private void disposeUserIfNeededLocked(@NonNull UserRecord userRecord) {
         // If there are no records left and the user is no longer current then go ahead
         // and purge the user record and all of its associated state.  If the user is current
         // then leave it alone since we might be connected to a route or want to query
         // the same route information again soon.
-        if (userRecord.mUserId != mCurrentUserId
+        if (!isUserActiveLocked(userRecord.mUserId)
                 && userRecord.mRouterRecords.isEmpty()
                 && userRecord.mManagerRecords.isEmpty()) {
             if (DEBUG) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index e61f553..440178a 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -17,7 +17,9 @@
 package com.android.server.media;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
+import android.app.UserSwitchObserver;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
@@ -61,7 +63,9 @@
 import android.util.TimeUtils;
 
 import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
 import com.android.server.Watchdog;
+import com.android.server.pm.UserManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -102,9 +106,10 @@
     // State guarded by mLock.
     private final Object mLock = new Object();
 
+    private final UserManagerInternal mUserManagerInternal;
     private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
     private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
-    private int mCurrentUserId = -1;
+    private int mCurrentActiveUserId = -1;
     private final IAudioService mAudioService;
     private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
     private final Handler mHandler = new Handler();
@@ -130,6 +135,7 @@
         mBluetoothA2dpRouteId =
                 res.getString(com.android.internal.R.string.bluetooth_a2dp_audio_route_id);
 
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         mAudioService = IAudioService.Stub.asInterface(
                 ServiceManager.getService(Context.AUDIO_SERVICE));
         mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context);
@@ -217,18 +223,27 @@
         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
     }
 
-    public void systemRunning() {
-        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
-        mContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (intent.getAction().equals(Intent.ACTION_USER_SWITCHED)) {
-                    switchUser();
-                }
-            }
-        }, filter);
-
-        switchUser();
+    /**
+     * Initializes the MediaRouter service.
+     *
+     * @throws RemoteException If an error occurs while registering the {@link UserSwitchObserver}.
+     */
+    @RequiresPermission(
+            anyOf = {
+                "android.permission.INTERACT_ACROSS_USERS",
+                "android.permission.INTERACT_ACROSS_USERS_FULL"
+            })
+    public void systemRunning() throws RemoteException {
+        ActivityManager.getService()
+                .registerUserSwitchObserver(
+                        new UserSwitchObserver() {
+                            @Override
+                            public void onUserSwitchComplete(int newUserId) {
+                                updateRunningUserAndProfiles(newUserId);
+                            }
+                        },
+                        TAG);
+        updateRunningUserAndProfiles(ActivityManager.getCurrentUser());
     }
 
     @Override
@@ -448,7 +463,7 @@
         pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)");
         pw.println();
         pw.println("Global state");
-        pw.println("  mCurrentUserId=" + mCurrentUserId);
+        pw.println("  mCurrentUserId=" + mCurrentActiveUserId);
 
         synchronized (mLock) {
             final int count = mUserRecords.size();
@@ -702,26 +717,31 @@
         }
     }
 
-    void switchUser() {
+    /**
+     * Starts all {@link UserRecord user records} associated with the active user (whose ID is
+     * {@code newActiveUserId}) or the active user's profiles.
+     *
+     * <p>All other records are stopped, and those without associated client records are removed.
+     */
+    private void updateRunningUserAndProfiles(int newActiveUserId) {
         synchronized (mLock) {
-            int userId = ActivityManager.getCurrentUser();
-            if (mCurrentUserId != userId) {
-                final int oldUserId = mCurrentUserId;
-                mCurrentUserId = userId; // do this first
-
-                UserRecord oldUser = mUserRecords.get(oldUserId);
-                if (oldUser != null) {
-                    oldUser.mHandler.sendEmptyMessage(UserHandler.MSG_STOP);
-                    disposeUserIfNeededLocked(oldUser); // since no longer current user
-                }
-
-                UserRecord newUser = mUserRecords.get(userId);
-                if (newUser != null) {
-                    newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START);
+            if (mCurrentActiveUserId != newActiveUserId) {
+                mCurrentActiveUserId = newActiveUserId;
+                for (int i = 0; i < mUserRecords.size(); i++) {
+                    int userId = mUserRecords.keyAt(i);
+                    UserRecord userRecord = mUserRecords.valueAt(i);
+                    if (isUserActiveLocked(userId)) {
+                        // userId corresponds to the active user, or one of its profiles. We
+                        // ensure the associated structures are initialized.
+                        userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
+                    } else {
+                        userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_STOP);
+                        disposeUserIfNeededLocked(userRecord);
+                    }
                 }
             }
         }
-        mService2.switchUser();
+        mService2.updateRunningUserAndProfiles(newActiveUserId);
     }
 
     void clientDied(ClientRecord clientRecord) {
@@ -776,8 +796,10 @@
         clientRecord.mGroupId = groupId;
         if (groupId != null) {
             userRecord.addToGroup(groupId, clientRecord);
-            userRecord.mHandler.obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
-                .sendToTarget();
+            userRecord
+                    .mHandler
+                    .obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
+                    .sendToTarget();
         }
     }
 
@@ -863,9 +885,13 @@
                                 clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId);
                         if (group != null) {
                             group.mSelectedRouteId = routeId;
-                            clientRecord.mUserRecord.mHandler.obtainMessage(
-                                UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, clientRecord.mGroupId)
-                                .sendToTarget();
+                            clientRecord
+                                    .mUserRecord
+                                    .mHandler
+                                    .obtainMessage(
+                                            UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED,
+                                            clientRecord.mGroupId)
+                                    .sendToTarget();
                         }
                     }
                 }
@@ -897,7 +923,7 @@
         if (DEBUG) {
             Slog.d(TAG, userRecord + ": Initialized");
         }
-        if (userRecord.mUserId == mCurrentUserId) {
+        if (isUserActiveLocked(userRecord.mUserId)) {
             userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
         }
     }
@@ -907,8 +933,7 @@
         // and purge the user record and all of its associated state.  If the user is current
         // then leave it alone since we might be connected to a route or want to query
         // the same route information again soon.
-        if (userRecord.mUserId != mCurrentUserId
-                && userRecord.mClientRecords.isEmpty()) {
+        if (!isUserActiveLocked(userRecord.mUserId) && userRecord.mClientRecords.isEmpty()) {
             if (DEBUG) {
                 Slog.d(TAG, userRecord + ": Disposed");
             }
@@ -917,6 +942,14 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile
+     * of the active user, returns {@code false} otherwise.
+     */
+    private boolean isUserActiveLocked(int userId) {
+        return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId;
+    }
+
     private void initializeClientLocked(ClientRecord clientRecord) {
         if (DEBUG) {
             Slog.d(TAG, clientRecord + ": Registered");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c2df904d..a92b65e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3796,13 +3796,13 @@
         }
 
         private void createNotificationChannelsImpl(String pkg, int uid,
-                ParceledListSlice channelsList) {
-            createNotificationChannelsImpl(pkg, uid, channelsList,
+                ParceledListSlice channelsList, boolean fromTargetApp) {
+            createNotificationChannelsImpl(pkg, uid, channelsList, fromTargetApp,
                     ActivityTaskManager.INVALID_TASK_ID);
         }
 
         private void createNotificationChannelsImpl(String pkg, int uid,
-                ParceledListSlice channelsList, int startingTaskId) {
+                ParceledListSlice channelsList, boolean fromTargetApp, int startingTaskId) {
             List<NotificationChannel> channels = channelsList.getList();
             final int channelsSize = channels.size();
             ParceledListSlice<NotificationChannel> oldChannels =
@@ -3814,7 +3814,7 @@
                 final NotificationChannel channel = channels.get(i);
                 Objects.requireNonNull(channel, "channel in list is null");
                 needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid,
-                        channel, true /* fromTargetApp */,
+                        channel, fromTargetApp,
                         mConditionProviders.isPackageOrComponentAllowed(
                                 pkg, UserHandle.getUserId(uid)));
                 if (needsPolicyFileChange) {
@@ -3850,6 +3850,7 @@
         @Override
         public void createNotificationChannels(String pkg, ParceledListSlice channelsList) {
             checkCallerIsSystemOrSameApp(pkg);
+            boolean fromTargetApp = !isCallerSystemOrPhone();  // if not system, it's from the app
             int taskId = ActivityTaskManager.INVALID_TASK_ID;
             try {
                 int uid = mPackageManager.getPackageUid(pkg, 0,
@@ -3858,14 +3859,15 @@
             } catch (RemoteException e) {
                 // Do nothing
             }
-            createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, taskId);
+            createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, fromTargetApp,
+                    taskId);
         }
 
         @Override
         public void createNotificationChannelsForPackage(String pkg, int uid,
                 ParceledListSlice channelsList) {
             enforceSystemOrSystemUI("only system can call this");
-            createNotificationChannelsImpl(pkg, uid, channelsList);
+            createNotificationChannelsImpl(pkg, uid, channelsList, false /* fromTargetApp */);
         }
 
         @Override
@@ -3880,7 +3882,8 @@
                     CONVERSATION_CHANNEL_ID_FORMAT, parentId, conversationId));
             conversationChannel.setConversationId(parentId, conversationId);
             createNotificationChannelsImpl(
-                    pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel)));
+                    pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel)),
+                    false /* fromTargetApp */);
             mRankingHandler.requestSort();
             handleSavePolicyFile();
         }
@@ -4966,7 +4969,16 @@
             }
             enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
 
-            return mZenModeHelper.addAutomaticZenRule(pkg, automaticZenRule,
+            // If the calling app is the system (from any user), take the package name from the
+            // rule's owner rather than from the caller's package.
+            String rulePkg = pkg;
+            if (isCallingAppIdSystem()) {
+                if (automaticZenRule.getOwner() != null) {
+                    rulePkg = automaticZenRule.getOwner().getPackageName();
+                }
+            }
+
+            return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
                     "addAutomaticZenRule");
         }
 
@@ -9721,6 +9733,12 @@
         return uid == Process.SYSTEM_UID;
     }
 
+    protected boolean isCallingAppIdSystem() {
+        final int uid = Binder.getCallingUid();
+        final int appid = UserHandle.getAppId(uid);
+        return appid == Process.SYSTEM_UID;
+    }
+
     protected boolean isUidSystemOrPhone(int uid) {
         final int appid = UserHandle.getAppId(uid);
         return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index d8aa469..9791158 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -916,7 +916,7 @@
                 throw new IllegalArgumentException("Reserved id");
             }
             NotificationChannel existing = r.channels.get(channel.getId());
-            if (existing != null && fromTargetApp) {
+            if (existing != null) {
                 // Actually modifying an existing channel - keep most of the existing settings
                 if (existing.isDeleted()) {
                     // The existing channel was deleted - undelete it.
@@ -1002,9 +1002,7 @@
                 }
                 if (fromTargetApp) {
                     channel.setLockscreenVisibility(r.visibility);
-                    channel.setAllowBubbles(existing != null
-                            ? existing.getAllowBubbles()
-                            : NotificationChannel.DEFAULT_ALLOW_BUBBLE);
+                    channel.setAllowBubbles(NotificationChannel.DEFAULT_ALLOW_BUBBLE);
                 }
                 clearLockedFieldsLocked(channel);
 
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index d426679..4c23ab8 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -326,7 +326,7 @@
 
     public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
             String reason) {
-        if (!isSystemRule(automaticZenRule)) {
+        if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
             if (component == null) {
                 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
@@ -582,11 +582,6 @@
         }
     }
 
-    private boolean isSystemRule(AutomaticZenRule rule) {
-        return rule.getOwner() != null
-                && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
-    }
-
     private ServiceInfo getServiceInfo(ComponentName owner) {
         Intent queryIntent = new Intent();
         queryIntent.setComponent(owner);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 06458d1..37bfbb1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -366,14 +366,6 @@
     @GuardedBy("mLock")
     private boolean mStageDirInUse = false;
 
-    /**
-     * True if the installation is already in progress. This is used to prevent the caller
-     * from {@link #commit(IntentSender, boolean) committing} the session again while the
-     * installation is still in progress.
-     */
-    @GuardedBy("mLock")
-    private boolean mInstallationInProgress = false;
-
     /** Permissions have been accepted by the user (see {@link #setPermissionsResult}) */
     @GuardedBy("mLock")
     private boolean mPermissionsManuallyAccepted = false;
@@ -1669,14 +1661,6 @@
             }
         }
 
-        synchronized (mLock) {
-            if (mInstallationInProgress) {
-                throw new IllegalStateException("Installation is already in progress. Don't "
-                        + "commit session=" + sessionId + " again.");
-            }
-            mInstallationInProgress = true;
-        }
-
         dispatchSessionSealed();
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 0ae92b4..32ee21c 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -616,6 +616,10 @@
         grantPermissionsToSystemPackage(pm, getDefaultCaptivePortalLoginPackage(), userId,
                 NOTIFICATION_PERMISSIONS);
 
+        // Dock Manager
+        grantPermissionsToSystemPackage(pm, getDefaultDockManagerPackage(), userId,
+                NOTIFICATION_PERMISSIONS);
+
         // Camera
         grantPermissionsToSystemPackage(pm,
                 getDefaultSystemHandlerActivityPackage(pm, MediaStore.ACTION_IMAGE_CAPTURE, userId),
@@ -932,6 +936,10 @@
         return mContext.getString(R.string.config_defaultCaptivePortalLoginPackageName);
     }
 
+    private String getDefaultDockManagerPackage() {
+        return mContext.getString(R.string.config_defaultDockManagerPackageName);
+    }
+
     @SafeVarargs
     private final void grantPermissionToEachSystemPackage(PackageManagerWrapper pm,
             ArrayList<String> packages, int userId, Set<String>... permissions) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 725fb3f..377a651 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1033,7 +1033,7 @@
         super(context);
 
         mContext = context;
-        mBinderService = new BinderService();
+        mBinderService = new BinderService(mContext);
         mLocalService = new LocalService();
         mNativeWrapper = injector.createNativeWrapper();
         mSystemProperties = injector.createSystemPropertiesWrapper();
@@ -5465,12 +5465,17 @@
 
     @VisibleForTesting
     final class BinderService extends IPowerManager.Stub {
+        private final PowerManagerShellCommand mShellCommand;
+
+        BinderService(Context context) {
+            mShellCommand = new PowerManagerShellCommand(context, this);
+        }
+
         @Override
         public void onShellCommand(FileDescriptor in, FileDescriptor out,
                 FileDescriptor err, String[] args, ShellCallback callback,
                 ResultReceiver resultReceiver) {
-            (new PowerManagerShellCommand(this)).exec(
-                    this, in, out, err, args, callback, resultReceiver);
+            mShellCommand.exec(this, in, out, err, args, callback, resultReceiver);
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
index a9b33ed..9439b76 100644
--- a/services/core/java/com/android/server/power/PowerManagerShellCommand.java
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -16,10 +16,15 @@
 
 package com.android.server.power;
 
+import android.content.Context;
 import android.content.Intent;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.os.PowerManagerInternal;
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.util.SparseArray;
+import android.view.Display;
 
 import java.io.PrintWriter;
 import java.util.List;
@@ -27,9 +32,13 @@
 class PowerManagerShellCommand extends ShellCommand {
     private static final int LOW_POWER_MODE_ON = 1;
 
-    final PowerManagerService.BinderService mService;
+    private final Context mContext;
+    private final PowerManagerService.BinderService mService;
 
-    PowerManagerShellCommand(PowerManagerService.BinderService service) {
+    private SparseArray<WakeLock> mProxWakelocks = new SparseArray<>();
+
+    PowerManagerShellCommand(Context context, PowerManagerService.BinderService service) {
+        mContext = context;
         mService = service;
     }
 
@@ -52,6 +61,8 @@
                     return runSuppressAmbientDisplay();
                 case "list-ambient-display-suppression-tokens":
                     return runListAmbientDisplaySuppressionTokens();
+                case "set-prox":
+                    return runSetProx();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -117,6 +128,56 @@
 
         return 0;
     }
+
+    /** TODO: Consider updating this code to support all wakelock types. */
+    private int runSetProx() throws RemoteException {
+        PrintWriter pw = getOutPrintWriter();
+        final boolean acquire;
+        switch (getNextArgRequired().toLowerCase()) {
+            case "list":
+                pw.println("Wakelocks:");
+                pw.println(mProxWakelocks);
+                return 0;
+            case "acquire":
+                acquire = true;
+                break;
+            case "release":
+                acquire = false;
+                break;
+            default:
+                pw.println("Error: Allowed options are 'list' 'enable' and 'disable'.");
+                return -1;
+        }
+
+        int displayId = Display.INVALID_DISPLAY;
+        String displayOption = getNextArg();
+        if ("-d".equals(displayOption)) {
+            String idStr = getNextArg();
+            displayId = Integer.parseInt(idStr);
+            if (displayId < 0) {
+                pw.println("Error: Specified displayId (" + idStr + ") must a non-negative int.");
+                return -1;
+            }
+        }
+
+        int wakelockIndex = displayId + 1; // SparseArray doesn't support negative indexes
+        WakeLock wakelock = mProxWakelocks.get(wakelockIndex);
+        if (wakelock == null) {
+            PowerManager pm = mContext.getSystemService(PowerManager.class);
+            wakelock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
+                        "PowerManagerShellCommand[" + displayId + "]", displayId);
+            mProxWakelocks.put(wakelockIndex, wakelock);
+        }
+
+        if (acquire) {
+            wakelock.acquire();
+        } else {
+            wakelock.release();
+        }
+        pw.println(wakelock);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -138,6 +199,11 @@
         pw.println("    ambient display");
         pw.println("  list-ambient-display-suppression-tokens");
         pw.println("    prints the tokens used to suppress ambient display");
+        pw.println("  set-prox [list|acquire|release] (-d <display_id>)");
+        pw.println("    Acquires the proximity sensor wakelock. Wakelock is associated with");
+        pw.println("    a specific display if specified. 'list' lists wakelocks previously");
+        pw.println("    created by set-prox including their held status.");
+
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 414d927..dd870a8 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1157,6 +1157,8 @@
                     Slog.w(TAG, "WallpaperService is not connected yet");
                     return;
                 }
+                TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+                t.traceBegin("WPMS.connectLocked-" + wallpaper.wallpaperComponent);
                 if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
                 mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId,
                         null /* options */);
@@ -1173,6 +1175,7 @@
                                 false /* fromUser */, wallpaper, null /* reply */);
                     }
                 }
+                t.traceEnd();
             }
 
             void disconnectLocked() {
@@ -1322,6 +1325,8 @@
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
+            TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+            t.traceBegin("WPMS.onServiceConnected-" + name);
             synchronized (mLock) {
                 if (mWallpaper.connection == this) {
                     mService = IWallpaperService.Stub.asInterface(service);
@@ -1337,6 +1342,7 @@
                     mContext.getMainThreadHandler().removeCallbacks(mTryToRebindRunnable);
                 }
             }
+            t.traceEnd();
         }
 
         @Override
@@ -1544,6 +1550,8 @@
         public void engineShown(IWallpaperEngine engine) {
             synchronized (mLock) {
                 if (mReply != null) {
+                    TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+                    t.traceBegin("WPMS.mReply.sendResult");
                     final long ident = Binder.clearCallingIdentity();
                     try {
                         mReply.sendResult(null);
@@ -1551,6 +1559,7 @@
                         Binder.restoreCallingIdentity(ident);
                         Slog.d(TAG, "failed to send callback!", e);
                     }
+                    t.traceEnd();
                     mReply = null;
                 }
             }
@@ -3049,6 +3058,8 @@
             return true;
         }
 
+        TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+        t.traceBegin("WPMS.bindWallpaperComponentLocked-" + componentName);
         try {
             if (componentName == null) {
                 componentName = mDefaultWallpaperComponent;
@@ -3181,6 +3192,8 @@
             }
             Slog.w(TAG, msg);
             return false;
+        } finally {
+            t.traceEnd();
         }
         return true;
     }
@@ -3225,7 +3238,10 @@
     }
 
     private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
+        TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+        t.traceBegin("WPMS.attachServiceLocked");
         conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
+        t.traceEnd();
     }
 
     private void notifyCallbacksLocked(WallpaperData wallpaper) {
@@ -3351,6 +3367,8 @@
     }
 
     void saveSettingsLocked(int userId) {
+        TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
+        t.traceBegin("WPMS.saveSettingsLocked-" + userId);
         JournaledFile journal = makeJournaledFile(userId);
         FileOutputStream fstream = null;
         try {
@@ -3379,6 +3397,7 @@
             IoUtils.closeQuietly(fstream);
             journal.rollback();
         }
+        t.traceEnd();
     }
 
 
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index eca2e74..741141d 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1347,8 +1347,38 @@
         }
     }
 
+    /**
+     * Return {@code true} when the given Activity is a relative Task root. That is, the rest of
+     * the Activities in the Task should be finished when it finishes. Otherwise, return {@code
+     * false}.
+     */
+    private boolean isRelativeTaskRootActivity(ActivityRecord r, ActivityRecord taskRoot) {
+        // Not a relative root if the given Activity is not the root Activity of its TaskFragment.
+        final TaskFragment taskFragment = r.getTaskFragment();
+        if (r != taskFragment.getActivity(ar -> !ar.finishing || ar == r,
+                false /* traverseTopToBottom */)) {
+            return false;
+        }
+
+        // The given Activity is the relative Task root if its TaskFragment is a companion
+        // TaskFragment to the taskRoot (i.e. the taskRoot TF will be finished together).
+        return taskRoot.getTaskFragment().getCompanionTaskFragment() == taskFragment;
+    }
+
+    private boolean isTopActivityInTaskFragment(ActivityRecord activity) {
+        return activity.getTaskFragment().topRunningActivity() == activity;
+    }
+
+    private void requestCallbackFinish(IRequestFinishCallback callback) {
+        try {
+            callback.requestFinish();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to invoke request finish callback", e);
+        }
+    }
+
     @Override
-    public void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
+    public void onBackPressed(IBinder token, IRequestFinishCallback callback) {
         final long origId = Binder.clearCallingIdentity();
         try {
             final Intent baseActivityIntent;
@@ -1358,20 +1388,29 @@
                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
                 if (r == null) return;
 
-                if (mService.mWindowOrganizerController.mTaskOrganizerController
+                final Task task = r.getTask();
+                final ActivityRecord root = task.getRootActivity(false /*ignoreRelinquishIdentity*/,
+                        true /*setToBottomIfNone*/);
+                final boolean isTaskRoot = r == root;
+                if (isTaskRoot) {
+                    if (mService.mWindowOrganizerController.mTaskOrganizerController
                         .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) {
-                    // This task is handled by a task organizer that has requested the back pressed
-                    // callback.
+                        // This task is handled by a task organizer that has requested the back
+                        // pressed callback.
+                        return;
+                    }
+                } else if (!isRelativeTaskRootActivity(r, root)) {
+                    // Finish the Activity if the activity is not the task root or relative root.
+                    requestCallbackFinish(callback);
                     return;
                 }
 
-                final Task task = r.getTask();
-                isLastRunningActivity = task.topRunningActivity() == r;
+                isLastRunningActivity = isTopActivityInTaskFragment(isTaskRoot ? root : r);
 
-                final boolean isBaseActivity = r.mActivityComponent.equals(task.realActivity);
-                baseActivityIntent = isBaseActivity ? r.intent : null;
+                final boolean isBaseActivity = root.mActivityComponent.equals(task.realActivity);
+                baseActivityIntent = isBaseActivity ? root.intent : null;
 
-                launchedFromHome = r.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
+                launchedFromHome = root.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
             }
 
             // If the activity is one of the main entry points for the application, then we should
@@ -1386,16 +1425,12 @@
             if (baseActivityIntent != null && isLastRunningActivity
                     && ((launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent))
                         || isLauncherActivity(baseActivityIntent.getComponent()))) {
-                moveActivityTaskToBack(token, false /* nonRoot */);
+                moveActivityTaskToBack(token, true /* nonRoot */);
                 return;
             }
 
             // The default option for handling the back button is to finish the Activity.
-            try {
-                callback.requestFinish();
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to invoke request finish callback", e);
-            }
+            requestCallbackFinish(callback);
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ccab968..fc15890 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1750,6 +1750,7 @@
         }
 
         prevDc.mClosingApps.remove(this);
+        prevDc.getDisplayPolicy().removeRelaunchingApp(this);
 
         if (prevDc.mFocusedApp == this) {
             prevDc.setFocusedApp(null);
@@ -3969,6 +3970,9 @@
     void startRelaunching() {
         if (mPendingRelaunchCount == 0) {
             mRelaunchStartTime = SystemClock.elapsedRealtime();
+            if (mVisibleRequested) {
+                mDisplayContent.getDisplayPolicy().addRelaunchingApp(this);
+            }
         }
         clearAllDrawn();
 
@@ -3982,7 +3986,7 @@
             mPendingRelaunchCount--;
             if (mPendingRelaunchCount == 0 && !isClientVisible()) {
                 // Don't count if the client won't report drawn.
-                mRelaunchStartTime = 0;
+                finishOrAbortReplacingWindow();
             }
         } else {
             // Update keyguard flags upon finishing relaunch.
@@ -4003,7 +4007,12 @@
             return;
         }
         mPendingRelaunchCount = 0;
+        finishOrAbortReplacingWindow();
+    }
+
+    void finishOrAbortReplacingWindow() {
         mRelaunchStartTime = 0;
+        mDisplayContent.getDisplayPolicy().removeRelaunchingApp(this);
     }
 
     /**
@@ -5112,6 +5121,9 @@
             mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
         }
         logAppCompatState();
+        if (!visible) {
+            finishOrAbortReplacingWindow();
+        }
     }
 
     /**
@@ -6862,6 +6874,10 @@
         if (r == null || r.getParent() == null) {
             return INVALID_TASK_ID;
         }
+        return getTaskForActivityLocked(r, onlyRoot);
+    }
+
+    static int getTaskForActivityLocked(ActivityRecord r, boolean onlyRoot) {
         final Task task = r.task;
         if (onlyRoot && r.compareTo(task.getRootActivity(
                 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index dc69ca6..eec7801 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2247,12 +2247,6 @@
                 ? targetTask.getTopNonFinishingActivity()
                 : targetTaskTop;
 
-        // At this point we are certain we want the task moved to the front. If we need to dismiss
-        // any other always-on-top root tasks, now is the time to do it.
-        if (targetTaskTop.canTurnScreenOn() && mService.isDreaming()) {
-            targetTaskTop.mTaskSupervisor.wakeUp("recycleTask#turnScreenOnFlag");
-        }
-
         if (mMovedToFront) {
             // We moved the task to front, use starting window to hide initial drawn delay.
             targetTaskTop.showStartingWindow(true /* taskSwitch */);
@@ -2264,6 +2258,12 @@
         // And for paranoia, make sure we have correctly resumed the top activity.
         resumeTargetRootTaskIfNeeded();
 
+        // This is moving an existing task to front. But since dream activity has a higher z-order
+        // to cover normal activities, it needs the awakening event to be dismissed.
+        if (mService.isDreaming() && targetTaskTop.canTurnScreenOn()) {
+            targetTaskTop.mTaskSupervisor.wakeUp("recycleTask#turnScreenOnFlag");
+        }
+
         mLastStartActivityRecord = targetTaskTop;
         return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
     }
@@ -2394,7 +2394,7 @@
                             mStartActivity.mUserId);
             if (act != null) {
                 final Task task = act.getTask();
-                boolean actuallyMoved = task.moveActivityToFrontLocked(act);
+                boolean actuallyMoved = task.moveActivityToFront(act);
                 if (actuallyMoved) {
                     // Only record if the activity actually moved.
                     mMovedToTopActivity = act;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index fe691c6..54664f5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -27,6 +27,7 @@
 import static android.app.ActivityManager.START_FLAG_NATIVE_DEBUGGING;
 import static android.app.ActivityManager.START_FLAG_TRACK_ALLOCATION;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
 import static android.app.WaitResult.INVALID_DELAY;
@@ -2592,6 +2593,10 @@
                         // Apply options to prevent pendingOptions be taken when scheduling
                         // activity lifecycle transaction to make sure the override pending app
                         // transition will be applied immediately.
+                        if (activityOptions.getAnimationType() == ANIM_REMOTE_ANIMATION) {
+                            targetActivity.mPendingRemoteAnimation =
+                                    activityOptions.getRemoteAnimationAdapter();
+                        }
                         targetActivity.applyOptionsAnimation();
                         if (activityOptions != null && activityOptions.getLaunchCookie() != null) {
                             targetActivity.mLaunchCookie = activityOptions.getLaunchCookie();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2688ff7..2c289c9 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -282,6 +282,12 @@
 
     private final ArraySet<WindowState> mInsetsSourceWindowsExceptIme = new ArraySet<>();
 
+    /** Apps which are controlling the appearance of system bars */
+    private final ArraySet<ActivityRecord> mSystemBarColorApps = new ArraySet<>();
+
+    /** Apps which are relaunching and were controlling the appearance of system bars */
+    private final ArraySet<ActivityRecord> mRelaunchingSystemBarColorApps = new ArraySet<>();
+
     private boolean mIsFreeformWindowOverlappingWithNavBar;
 
     private boolean mLastImmersiveMode;
@@ -1550,6 +1556,7 @@
         mStatusBarBackgroundWindows.clear();
         mStatusBarColorCheckedBounds.setEmpty();
         mStatusBarBackgroundCheckedBounds.setEmpty();
+        mSystemBarColorApps.clear();
 
         mAllowLockscreenWhenOn = false;
         mShowingDream = false;
@@ -1626,6 +1633,7 @@
                             win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS,
                             new Rect(win.getFrame())));
                     mStatusBarColorCheckedBounds.union(sTmpRect);
+                    addSystemBarColorApp(win);
                 }
             }
 
@@ -1638,6 +1646,7 @@
             if (isOverlappingWithNavBar) {
                 if (mNavBarColorWindowCandidate == null) {
                     mNavBarColorWindowCandidate = win;
+                    addSystemBarColorApp(win);
                 }
                 if (mNavBarBackgroundWindow == null) {
                     mNavBarBackgroundWindow = win;
@@ -1656,9 +1665,11 @@
             }
         } else if (win.isDimming()) {
             if (mStatusBar != null) {
-                addStatusBarAppearanceRegionsForDimmingWindow(
+                if (addStatusBarAppearanceRegionsForDimmingWindow(
                         win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS,
-                        mStatusBar.getFrame(), win.getBounds(), win.getFrame());
+                        mStatusBar.getFrame(), win.getBounds(), win.getFrame())) {
+                    addSystemBarColorApp(win);
+                }
             }
             if (isOverlappingWithNavBar && mNavBarColorWindowCandidate == null) {
                 mNavBarColorWindowCandidate = win;
@@ -1666,18 +1677,21 @@
         }
     }
 
-    private void addStatusBarAppearanceRegionsForDimmingWindow(int appearance, Rect statusBarFrame,
-            Rect winBounds, Rect winFrame) {
+    /**
+     * Returns true if mStatusBarAppearanceRegionList is changed.
+     */
+    private boolean addStatusBarAppearanceRegionsForDimmingWindow(
+            int appearance, Rect statusBarFrame, Rect winBounds, Rect winFrame) {
         if (!sTmpRect.setIntersect(winBounds, statusBarFrame)) {
-            return;
+            return false;
         }
         if (mStatusBarColorCheckedBounds.contains(sTmpRect)) {
-            return;
+            return false;
         }
         if (appearance == 0 || !sTmpRect2.setIntersect(winFrame, statusBarFrame)) {
             mStatusBarAppearanceRegionList.add(new AppearanceRegion(0, new Rect(winBounds)));
             mStatusBarColorCheckedBounds.union(sTmpRect);
-            return;
+            return true;
         }
         // A dimming window can divide status bar into different appearance regions (up to 3).
         // +---------+-------------+---------+
@@ -1706,6 +1720,14 @@
             // We don't have vertical status bar yet, so we don't handle the other orientation.
         }
         mStatusBarColorCheckedBounds.union(sTmpRect);
+        return true;
+    }
+
+    private void addSystemBarColorApp(WindowState win) {
+        final ActivityRecord app = win.mActivityRecord;
+        if (app != null) {
+            mSystemBarColorApps.add(app);
+        }
     }
 
     /**
@@ -2202,6 +2224,25 @@
         return mDisplayContent.getInsetsPolicy();
     }
 
+    /**
+     * Called when an app has started replacing its main window.
+     */
+    void addRelaunchingApp(ActivityRecord app) {
+        if (mSystemBarColorApps.contains(app)) {
+            mRelaunchingSystemBarColorApps.add(app);
+        }
+    }
+
+    /**
+     * Called when an app has finished replacing its main window or aborted.
+     */
+    void removeRelaunchingApp(ActivityRecord app) {
+        final boolean removed = mRelaunchingSystemBarColorApps.remove(app);
+        if (removed & mRelaunchingSystemBarColorApps.isEmpty()) {
+            updateSystemBarAttributes();
+        }
+    }
+
     void resetSystemBarAttributes() {
         mLastDisableFlags = 0;
         updateSystemBarAttributes();
@@ -2244,6 +2285,11 @@
         final int displayId = getDisplayId();
         final int disableFlags = win.getDisableFlags();
         final int opaqueAppearance = updateSystemBarsLw(win, disableFlags);
+        if (!mRelaunchingSystemBarColorApps.isEmpty()) {
+            // The appearance of system bars might change while relaunching apps. We don't report
+            // the intermediate state to system UI. Otherwise, it might trigger redundant effects.
+            return;
+        }
         final WindowState navColorWin = chooseNavigationColorWindowLw(mNavBarColorWindowCandidate,
                 mDisplayContent.mInputMethodWindow, mNavigationBarPosition);
         final boolean isNavbarColorManagedByIme =
@@ -2707,6 +2753,14 @@
             pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
             pw.println(mTopFullscreenOpaqueWindowState);
         }
+        if (!mSystemBarColorApps.isEmpty()) {
+            pw.print(prefix); pw.print("mSystemBarColorApps=");
+            pw.println(mSystemBarColorApps);
+        }
+        if (!mRelaunchingSystemBarColorApps.isEmpty()) {
+            pw.print(prefix); pw.print("mRelaunchingSystemBarColorApps=");
+            pw.println(mRelaunchingSystemBarColorApps);
+        }
         if (mNavBarColorWindowCandidate != null) {
             pw.print(prefix); pw.print("mNavBarColorWindowCandidate=");
             pw.println(mNavBarColorWindowCandidate);
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index ea82417..74a236b 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -501,12 +501,16 @@
 
             if (hasVisibleTaskbar(mainWindow)) {
                 cropBounds = new Rect(mActivityRecord.getBounds());
+
+                // Rounded corners should be displayed above the taskbar.
+                // It is important to call adjustBoundsForTaskbarUnchecked before offsetTo
+                // because taskbar bounds are in screen coordinates
+                adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds);
+
                 // Activity bounds are in screen coordinates while (0,0) for activity's surface
                 // control is at the top left corner of an app window so offsetting bounds
                 // accordingly.
                 cropBounds.offsetTo(0, 0);
-                // Rounded corners should be displayed above the taskbar.
-                adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds);
             }
 
             transaction
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 66d7af9..825e9e0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1408,13 +1408,26 @@
      * Reorder the history task so that the passed activity is brought to the front.
      * @return whether it was actually moved (vs already being top).
      */
-    final boolean moveActivityToFrontLocked(ActivityRecord newTop) {
+    final boolean moveActivityToFront(ActivityRecord newTop) {
         ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing and adding activity %s to root task at top "
                 + "callers=%s", newTop, Debug.getCallers(4));
-        int origDist = getDistanceFromTop(newTop);
-        positionChildAtTop(newTop);
+        final TaskFragment taskFragment = newTop.getTaskFragment();
+        boolean moved;
+        if (taskFragment != this) {
+            if (taskFragment.isEmbedded() && taskFragment.getNonFinishingActivityCount() == 1) {
+                taskFragment.mClearedForReorderActivityToFront = true;
+            }
+            newTop.reparent(this, POSITION_TOP);
+            moved = true;
+            if (taskFragment.isEmbedded()) {
+                mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController
+                        .onActivityReparentedToTask(newTop);
+            }
+        } else {
+            moved = moveChildToFront(newTop);
+        }
         updateEffectiveIntent();
-        return getDistanceFromTop(newTop) != origDist;
+        return moved;
     }
 
     @Override
@@ -1591,6 +1604,11 @@
                 removeChild(r, reason);
             });
         } else {
+            // Finish or destroy apps from the bottom to ensure that all the other activity have
+            // been finished and the top task in another task gets resumed when a top activity is
+            // removed. Otherwise, shell transitions wouldn't run because there would be no event
+            // that sets the transition ready.
+            final boolean traverseTopToBottom = !mTransitionController.isShellTransitionsEnabled();
             forAllActivities((r) -> {
                 if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) {
                     return;
@@ -1604,7 +1622,7 @@
                 } else {
                     r.destroyIfPossible(reason);
                 }
-            });
+            }, traverseTopToBottom);
         }
     }
 
@@ -3096,20 +3114,6 @@
         });
     }
 
-    void positionChildAtTop(ActivityRecord child) {
-        positionChildAt(child, POSITION_TOP);
-    }
-
-    void positionChildAt(ActivityRecord child, int position) {
-        if (child == null) {
-            Slog.w(TAG_WM,
-                    "Attempted to position of non-existing app");
-            return;
-        }
-
-        positionChildAt(position, child, false /* includeParents */);
-    }
-
     void setTaskDescription(TaskDescription taskDescription) {
         mTaskDescription = taskDescription;
     }
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 377c5b4..52df3ca 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -222,6 +222,14 @@
     private TaskFragment mAdjacentTaskFragment;
 
     /**
+     * Unlike the {@link mAdjacentTaskFragment}, the companion TaskFragment is not always visually
+     * adjacent to this one, but this TaskFragment will be removed by the organizer if the
+     * companion TaskFragment is removed.
+     */
+    @Nullable
+    private TaskFragment mCompanionTaskFragment;
+
+    /**
      * Prevents duplicate calls to onTaskAppeared.
      */
     boolean mTaskFragmentAppearedSent;
@@ -239,6 +247,12 @@
     boolean mClearedTaskFragmentForPip;
 
     /**
+     * The last running activity of the TaskFragment was removed and added to the top-most of the
+     * Task because it was launched with FLAG_ACTIVITY_REORDER_TO_FRONT.
+     */
+    boolean mClearedForReorderActivityToFront;
+
+    /**
      * When we are in the process of pausing an activity, before starting the
      * next one, this variable holds the activity that is currently being paused.
      *
@@ -289,6 +303,12 @@
     private final IBinder mFragmentToken;
 
     /**
+     * Whether to delay the call to {@link #updateOrganizedTaskFragmentSurface()} when there is a
+     * configuration change.
+     */
+    private boolean mDelayOrganizedTaskFragmentSurfaceUpdate;
+
+    /**
      * Whether to delay the last activity of TaskFragment being immediately removed while finishing.
      * This should only be set on a embedded TaskFragment, where the organizer can have the
      * opportunity to perform animations and finishing the adjacent TaskFragment.
@@ -388,6 +408,14 @@
         }
     }
 
+    void setCompanionTaskFragment(@Nullable TaskFragment companionTaskFragment) {
+        mCompanionTaskFragment = companionTaskFragment;
+    }
+
+    TaskFragment getCompanionTaskFragment() {
+        return mCompanionTaskFragment;
+    }
+
     void resetAdjacentTaskFragment() {
         // Reset the adjacent TaskFragment if its adjacent TaskFragment is also this TaskFragment.
         if (mAdjacentTaskFragment != null && mAdjacentTaskFragment.mAdjacentTaskFragment == this) {
@@ -1844,6 +1872,7 @@
         ActivityRecord r = topRunningActivity();
         mClearedTaskForReuse = false;
         mClearedTaskFragmentForPip = false;
+        mClearedForReorderActivityToFront = false;
 
         final ActivityRecord addingActivity = child.asActivityRecord();
         final boolean isAddingActivity = addingActivity != null;
@@ -2273,35 +2302,41 @@
 
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
-        // Task will animate differently.
-        if (mTaskFragmentOrganizer != null) {
-            mTmpPrevBounds.set(getBounds());
-        }
-
         super.onConfigurationChanged(newParentConfig);
 
-        final boolean shouldStartChangeTransition = shouldStartChangeTransition(mTmpPrevBounds);
-        if (shouldStartChangeTransition) {
-            initializeChangeTransition(mTmpPrevBounds);
-        }
         if (mTaskFragmentOrganizer != null) {
-            if (mTransitionController.isShellTransitionsEnabled()
-                    && !mTransitionController.isCollecting(this)) {
-                // TaskFragmentOrganizer doesn't have access to the surface for security reasons, so
-                // update the surface here if it is not collected by Shell transition.
-                updateOrganizedTaskFragmentSurface();
-            } else if (!mTransitionController.isShellTransitionsEnabled()
-                    && !shouldStartChangeTransition) {
-                // Update the surface here instead of in the organizer so that we can make sure
-                // it can be synced with the surface freezer for legacy app transition.
-                updateOrganizedTaskFragmentSurface();
-            }
+            updateOrganizedTaskFragmentSurface();
         }
 
         sendTaskFragmentInfoChanged();
     }
 
+    void deferOrganizedTaskFragmentSurfaceUpdate() {
+        mDelayOrganizedTaskFragmentSurfaceUpdate = true;
+    }
+
+    void continueOrganizedTaskFragmentSurfaceUpdate() {
+        mDelayOrganizedTaskFragmentSurfaceUpdate = false;
+        updateOrganizedTaskFragmentSurface();
+    }
+
     private void updateOrganizedTaskFragmentSurface() {
+        if (mDelayOrganizedTaskFragmentSurfaceUpdate) {
+            return;
+        }
+        if (mTransitionController.isShellTransitionsEnabled()
+                && !mTransitionController.isCollecting(this)) {
+            // TaskFragmentOrganizer doesn't have access to the surface for security reasons, so
+            // update the surface here if it is not collected by Shell transition.
+            updateOrganizedTaskFragmentSurfaceUnchecked();
+        } else if (!mTransitionController.isShellTransitionsEnabled() && !isAnimating()) {
+            // Update the surface here instead of in the organizer so that we can make sure
+            // it can be synced with the surface freezer for legacy app transition.
+            updateOrganizedTaskFragmentSurfaceUnchecked();
+        }
+    }
+
+    private void updateOrganizedTaskFragmentSurfaceUnchecked() {
         final SurfaceControl.Transaction t = getSyncTransaction();
         updateSurfacePosition(t);
         updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */);
@@ -2355,7 +2390,7 @@
     }
 
     /** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */
-    private boolean shouldStartChangeTransition(Rect startBounds) {
+    boolean shouldStartChangeTransition(Rect startBounds) {
         if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) {
             return false;
         }
@@ -2375,7 +2410,7 @@
     void setSurfaceControl(SurfaceControl sc) {
         super.setSurfaceControl(sc);
         if (mTaskFragmentOrganizer != null) {
-            updateOrganizedTaskFragmentSurface();
+            updateOrganizedTaskFragmentSurfaceUnchecked();
             // If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
             // emit the callbacks now.
             sendTaskFragmentAppeared();
@@ -2437,6 +2472,7 @@
                 positionInParent,
                 mClearedTaskForReuse,
                 mClearedTaskFragmentForPip,
+                mClearedForReorderActivityToFront,
                 calculateMinDimension());
     }
 
@@ -2715,6 +2751,16 @@
         return callback.test(this) ? this : null;
     }
 
+    /**
+     * Moves the passed child to front
+     * @return whether it was actually moved (vs already being top).
+     */
+    boolean moveChildToFront(WindowContainer newTop) {
+        int origDist = getDistanceFromTop(newTop);
+        positionChildAt(POSITION_TOP, newTop, false /* includeParents */);
+        return getDistanceFromTop(newTop) != origDist;
+    }
+
     String toFullString() {
         final StringBuilder sb = new StringBuilder(128);
         sb.append(this);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9c9d751..9db5170 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1883,7 +1883,7 @@
                 // Make this invalid which indicates a null attached frame.
                 outAttachedFrame.set(0, 0, -1, -1);
             }
-            outSizeCompatScale[0] = win.getSizeCompatScale();
+            outSizeCompatScale[0] = win.getSizeCompatScaleForClient();
         }
 
         Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 32a110e..557c0ef 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -39,6 +39,7 @@
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT;
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
@@ -48,6 +49,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
 import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
@@ -146,6 +148,8 @@
     @VisibleForTesting
     final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>();
 
+    private final Rect mTmpBounds = new Rect();
+
     WindowOrganizerController(ActivityTaskManagerService atm) {
         mService = atm;
         mGlobalLock = atm.mGlobalLock;
@@ -710,7 +714,7 @@
     }
 
     private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {
-        int effects = 0;
+        int effects = applyChanges(tr, c, null /* errorCallbackToken */);
         final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
 
         if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {
@@ -725,6 +729,10 @@
             effects = TRANSACT_EFFECTS_LIFECYCLE;
         }
 
+        if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING) != 0) {
+            tr.setDragResizing(c.getDragResizing(), DRAG_RESIZE_MODE_FREEFORM);
+        }
+
         final int childWindowingMode = c.getActivityWindowingMode();
         if (childWindowingMode > -1) {
             tr.setActivityWindowingMode(childWindowingMode);
@@ -767,6 +775,7 @@
     private int applyDisplayAreaChanges(DisplayArea displayArea,
             WindowContainerTransaction.Change c) {
         final int[] effects = new int[1];
+        effects[0] = applyChanges(displayArea, c, null /* errorCallbackToken */);
 
         if ((c.getChangeMask()
                 & WindowContainerTransaction.Change.CHANGE_IGNORE_ORIENTATION_REQUEST) != 0) {
@@ -787,6 +796,27 @@
         return effects[0];
     }
 
+    private int applyTaskFragmentChanges(@NonNull TaskFragment taskFragment,
+            @NonNull WindowContainerTransaction.Change c, @Nullable IBinder errorCallbackToken) {
+        if (taskFragment.isEmbeddedTaskFragmentInPip()) {
+            // No override from organizer for embedded TaskFragment in a PIP Task.
+            return 0;
+        }
+
+        // When the TaskFragment is resized, we may want to create a change transition for it, for
+        // which we want to defer the surface update until we determine whether or not to start
+        // change transition.
+        mTmpBounds.set(taskFragment.getBounds());
+        taskFragment.deferOrganizedTaskFragmentSurfaceUpdate();
+        final int effects = applyChanges(taskFragment, c, errorCallbackToken);
+        if (taskFragment.shouldStartChangeTransition(mTmpBounds)) {
+            taskFragment.initializeChangeTransition(mTmpBounds);
+        }
+        taskFragment.continueOrganizedTaskFragmentSurfaceUpdate();
+        mTmpBounds.set(0, 0, 0, 0);
+        return effects;
+    }
+
     private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
             int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
             @NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
@@ -975,6 +1005,14 @@
                 tf1.setAdjacentTaskFragment(tf2);
                 effects |= TRANSACT_EFFECTS_LIFECYCLE;
 
+                // Clear the focused app if the focused app is no longer visible after reset the
+                // adjacent TaskFragments.
+                if (tf2 == null && tf1.getDisplayContent().mFocusedApp != null
+                        && tf1.hasChild(tf1.getDisplayContent().mFocusedApp)
+                        && !tf1.shouldBeVisible(null /* starting */)) {
+                    tf1.getDisplayContent().setFocusedApp(null);
+                }
+
                 final Bundle bundle = hop.getLaunchOptions();
                 final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams =
                         bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams(
@@ -1088,6 +1126,22 @@
                 effects |= sanitizeAndApplyHierarchyOp(wc, hop);
                 break;
             }
+            case HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT: {
+                final IBinder fragmentToken = hop.getContainer();
+                final IBinder companionToken = hop.getCompanionContainer();
+                final TaskFragment fragment = mLaunchTaskFragments.get(fragmentToken);
+                final TaskFragment companion = companionToken != null ? mLaunchTaskFragments.get(
+                        companionToken) : null;
+                if (fragment == null || !fragment.isAttached()) {
+                    final Throwable exception = new IllegalArgumentException(
+                            "Not allowed to set companion on invalid fragment tokens");
+                    sendTaskFragmentOperationFailure(organizer, errorCallbackToken, fragment, type,
+                            exception);
+                    break;
+                }
+                fragment.setCompanionTaskFragment(companion);
+                break;
+            }
             default: {
                 // The other operations may change task order so they are skipped while in lock
                 // task mode. The above operations are still allowed because they don't move
@@ -1452,20 +1506,15 @@
     private int applyWindowContainerChange(WindowContainer wc,
             WindowContainerTransaction.Change c, @Nullable IBinder errorCallbackToken) {
         sanitizeWindowContainer(wc);
-        if (wc.asTaskFragment() != null && wc.asTaskFragment().isEmbeddedTaskFragmentInPip()) {
-            // No override from organizer for embedded TaskFragment in a PIP Task.
-            return 0;
+        if (wc.asDisplayArea() != null) {
+            return applyDisplayAreaChanges(wc.asDisplayArea(), c);
+        } else if (wc.asTask() != null) {
+            return applyTaskChanges(wc.asTask(), c);
+        } else if (wc.asTaskFragment() != null) {
+            return applyTaskFragmentChanges(wc.asTaskFragment(), c, errorCallbackToken);
+        } else {
+            return applyChanges(wc, c, errorCallbackToken);
         }
-
-        int effects = applyChanges(wc, c, errorCallbackToken);
-
-        if (wc instanceof DisplayArea) {
-            effects |= applyDisplayAreaChanges(wc.asDisplayArea(), c);
-        } else if (wc instanceof Task) {
-            effects |= applyTaskChanges(wc.asTask(), c);
-        }
-
-        return effects;
     }
 
     @Override
@@ -1630,6 +1679,12 @@
                 case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT:
                     enforceTaskFragmentOrganized(func, hop.getNewParent(), organizer);
                     break;
+                case HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT:
+                    enforceTaskFragmentOrganized(func, hop.getContainer(), organizer);
+                    if (hop.getCompanionContainer() != null) {
+                        enforceTaskFragmentOrganized(func, hop.getCompanionContainer(), organizer);
+                    }
+                    break;
                 case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS:
                     enforceTaskFragmentOrganized(func, hop.getContainer(), organizer);
                     if (hop.getAdjacentRoot() != null) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a42cec9..45606f9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1265,8 +1265,10 @@
         mGlobalScale = mInvGlobalScale = mSizeCompatScale = 1f;
     }
 
-    float getSizeCompatScale() {
-        return mSizeCompatScale;
+    float getSizeCompatScaleForClient() {
+        // If the size compat scale is because of the size compat bounds, we only scale down its
+        // coordinates at the server side without letting the client know.
+        return mToken.hasSizeCompatBounds() ? 1f : mSizeCompatScale;
     }
 
     /**
@@ -1535,10 +1537,11 @@
             mWmService.makeWindowFreezingScreenIfNeededLocked(this);
 
             // If the orientation is changing, or we're starting or ending a drag resizing action,
-            // then we need to hold off on unfreezing the display until this window has been
-            // redrawn; to do that, we need to go through the process of getting informed by the
-            // application when it has finished drawing.
-            if (getOrientationChanging() || dragResizingChanged) {
+            // or we're resizing an embedded Activity, then we need to hold off on unfreezing the
+            // display until this window has been redrawn; to do that, we need to go through the
+            // process of getting informed by the application when it has finished drawing.
+            if (getOrientationChanging() || dragResizingChanged
+                    || isEmbeddedActivityResizeChanged()) {
                 if (dragResizingChanged) {
                     ProtoLog.v(WM_DEBUG_RESIZE,
                             "Resize start waiting for draw, "
@@ -3863,7 +3866,8 @@
                 outFrames.attachedFrame.scale(mInvGlobalScale);
             }
         }
-        outFrames.sizeCompatScale = mSizeCompatScale;
+
+        outFrames.sizeCompatScale = getSizeCompatScaleForClient();
 
         // Note: in the cases where the window is tied to an activity, we should not send a
         // configuration update when the window has requested to be hidden. Doing so can lead to
@@ -4144,6 +4148,20 @@
         return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame);
     }
 
+    /**
+     * Whether this window belongs to a resizing embedded activity.
+     */
+    private boolean isEmbeddedActivityResizeChanged() {
+        if (mActivityRecord == null || !isVisibleRequested()) {
+            // No need to update if the window is in the background.
+            return false;
+        }
+
+        final TaskFragment embeddedTaskFragment = mActivityRecord.getOrganizedTaskFragment();
+        return embeddedTaskFragment != null
+                && mDisplayContent.mChangingContainers.contains(embeddedTaskFragment);
+    }
+
     boolean isDragResizeChanged() {
         return mDragResizing != computeDragResizing();
     }
@@ -6021,7 +6039,7 @@
             final long duration =
                     SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime;
             Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
-            mActivityRecord.mRelaunchStartTime = 0;
+            mActivityRecord.finishOrAbortReplacingWindow();
         }
         if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) {
             mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index cfb8014..a47c529 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -1490,6 +1490,38 @@
     }
 
     @Test
+    public void testSwitchUser() {
+        mockManageUsersGranted();
+        mockModifyGameModeGranted();
+
+        mockDeviceConfigBattery();
+        final Context context = InstrumentationRegistry.getContext();
+        GameManagerService gameManagerService = new GameManagerService(mMockContext,
+                mTestLooper.getLooper(), context.getFilesDir());
+        startUser(gameManagerService, USER_ID_1);
+        startUser(gameManagerService, USER_ID_2);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+        checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+                GameManager.GAME_MODE_BATTERY);
+        assertEquals(gameManagerService.getGameMode(mPackageName, USER_ID_1),
+                GameManager.GAME_MODE_BATTERY);
+
+        mockDeviceConfigAll();
+        switchUser(gameManagerService, USER_ID_1, USER_ID_2);
+        assertEquals(gameManagerService.getGameMode(mPackageName, USER_ID_2),
+                GameManager.GAME_MODE_STANDARD);
+        checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+                GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_PERFORMANCE);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_2);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+
+        switchUser(gameManagerService, USER_ID_2, USER_ID_1);
+        checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+                GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_PERFORMANCE);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_2);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+    }
+
     public void testResetInterventions_onDeviceConfigReset() throws Exception {
         mockModifyGameModeGranted();
         String configStringBefore =
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 9c615d1..ed369c0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -764,11 +764,13 @@
     @Test
     public void testGetSystemPreferredDisplayMode() throws Exception {
         SurfaceControl.DisplayMode displayMode1 = createFakeDisplayMode(0, 1920, 1080, 60f);
-        // preferred mode
+        // system preferred mode
         SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 3840, 2160, 60f);
+        // user preferred mode
+        SurfaceControl.DisplayMode displayMode3 = createFakeDisplayMode(2, 1920, 1080, 30f);
 
         SurfaceControl.DisplayMode[] modes =
-                new SurfaceControl.DisplayMode[]{displayMode1, displayMode2};
+                new SurfaceControl.DisplayMode[]{displayMode1, displayMode2, displayMode3};
         FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, 1);
         setUpDisplay(display);
         updateAvailableDisplays();
@@ -780,24 +782,43 @@
 
         DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
                 0).getDisplayDeviceInfoLocked();
-
         assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
-
         Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode1)).isTrue();
+
+        // Set the user preferred display mode
+        mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
+                new Display.Mode(
+                        displayMode3.width, displayMode3.height, displayMode3.refreshRate));
+        updateAvailableDisplays();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        displayDeviceInfo = mListener.addedDisplays.get(
+                0).getDisplayDeviceInfoLocked();
+        defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode3)).isTrue();
+
+        // clear the user preferred mode
+        mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(null);
+        updateAvailableDisplays();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        displayDeviceInfo = mListener.addedDisplays.get(
+                0).getDisplayDeviceInfoLocked();
+        defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
         assertThat(matches(defaultMode, displayMode2)).isTrue();
 
-        // Change the display and add new preferred mode
-        SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(2, 2340, 1080, 60f);
-        modes = new SurfaceControl.DisplayMode[]{displayMode1, displayMode2, addedDisplayInfo};
+        // Change the display and add new system preferred mode
+        SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(3, 2340, 1080, 20f);
+        modes = new SurfaceControl.DisplayMode[]{
+                displayMode1, displayMode2, displayMode3, addedDisplayInfo};
         display.dynamicInfo.supportedDisplayModes = modes;
-        display.dynamicInfo.preferredBootDisplayMode = 2;
+        display.dynamicInfo.preferredBootDisplayMode = 3;
         setUpDisplay(display);
         mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
 
         assertTrue(mListener.traversalRequested);
         assertThat(mListener.addedDisplays.size()).isEqualTo(1);
-        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays.size()).isEqualTo(3);
 
         DisplayDevice displayDevice = mListener.changedDisplays.get(0);
         displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java
index 0cff4f1..bb00634 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java
@@ -125,12 +125,9 @@
         mProbe.destroy();
         mProbe.enable();
 
-        AtomicInteger lux = new AtomicInteger(10);
-        mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
-
         verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
         verifyNoMoreInteractions(mSensorManager);
-        assertThat(lux.get()).isLessThan(0);
+        assertThat(mProbe.getMostRecentLux()).isLessThan(0);
     }
 
     @Test
@@ -323,15 +320,27 @@
     }
 
     @Test
-    public void testNoNextLuxWhenDestroyed() {
+    public void testDestroyAllowsAwaitLuxExactlyOnce() {
+        final float lastValue = 5.5f;
         mProbe.destroy();
 
-        AtomicInteger lux = new AtomicInteger(-20);
+        AtomicInteger lux = new AtomicInteger(10);
         mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
 
-        assertThat(lux.get()).isEqualTo(-1);
-        verify(mSensorManager, never()).registerListener(
+        verify(mSensorManager).registerListener(
                 mSensorEventListenerCaptor.capture(), any(), anyInt());
+        mSensorEventListenerCaptor.getValue().onSensorChanged(
+                new SensorEvent(mLightSensor, 1, 1, new float[]{lastValue}));
+
+        assertThat(lux.get()).isEqualTo(Math.round(lastValue));
+        verify(mSensorManager).unregisterListener(eq(mSensorEventListenerCaptor.getValue()));
+
+        lux.set(22);
+        mProbe.enable();
+        mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
+        mProbe.enable();
+
+        assertThat(lux.get()).isEqualTo(Math.round(lastValue));
         verifyNoMoreInteractions(mSensorManager);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 2094c93..cc68ba8 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -22,8 +22,6 @@
 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED;
 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED;
 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED;
-import static com.android.server.display.LogicalDisplay.DISPLAY_PHASE_DISABLED;
-import static com.android.server.display.LogicalDisplay.DISPLAY_PHASE_ENABLED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED;
 
@@ -55,8 +53,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.display.layout.Layout;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -89,7 +85,6 @@
     @Mock Resources mResourcesMock;
     @Mock IPowerManager mIPowerManagerMock;
     @Mock IThermalService mIThermalServiceMock;
-    @Mock DeviceStateToLayoutMap mDeviceStateToLayoutMapMock;
 
     @Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
 
@@ -135,13 +130,11 @@
         when(mResourcesMock.getIntArray(
                 com.android.internal.R.array.config_deviceStatesOnWhichToSleep))
                 .thenReturn(new int[]{0});
-        when(mDeviceStateToLayoutMapMock.get(-1)).thenReturn(new Layout());
 
         mLooper = new TestLooper();
         mHandler = new Handler(mLooper.getLooper());
         mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
-                mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
-                mDeviceStateToLayoutMapMock);
+                mListenerMock, new DisplayManagerService.SyncRoot(), mHandler);
     }
 
 
@@ -420,58 +413,6 @@
                 /* isBootCompleted= */true));
     }
 
-    @Test
-    public void testDeviceStateLocked() {
-        DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
-        DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
-
-        Layout layout = new Layout();
-        layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, true, true);
-        layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, false, false);
-        when(mDeviceStateToLayoutMapMock.get(0)).thenReturn(layout);
-
-        layout = new Layout();
-        layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, false, false);
-        layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, true, true);
-        when(mDeviceStateToLayoutMapMock.get(1)).thenReturn(layout);
-        when(mDeviceStateToLayoutMapMock.get(2)).thenReturn(layout);
-
-        LogicalDisplay display1 = add(device1);
-        assertEquals(info(display1).address, info(device1).address);
-        assertEquals(DEFAULT_DISPLAY, id(display1));
-
-        LogicalDisplay display2 = add(device2);
-        assertEquals(info(display2).address, info(device2).address);
-        // We can only have one default display
-        assertEquals(DEFAULT_DISPLAY, id(display1));
-
-        mLogicalDisplayMapper.setDeviceStateLocked(0, false);
-        mLooper.moveTimeForward(1000);
-        mLooper.dispatchAll();
-        assertEquals(DISPLAY_PHASE_ENABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device1).getPhase());
-        assertEquals(DISPLAY_PHASE_DISABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device2).getPhase());
-
-        mLogicalDisplayMapper.setDeviceStateLocked(1, false);
-        mLooper.moveTimeForward(1000);
-        mLooper.dispatchAll();
-        assertEquals(DISPLAY_PHASE_DISABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device1).getPhase());
-        assertEquals(DISPLAY_PHASE_ENABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device2).getPhase());
-
-        mLogicalDisplayMapper.setDeviceStateLocked(2, false);
-        mLooper.moveTimeForward(1000);
-        mLooper.dispatchAll();
-        assertEquals(DISPLAY_PHASE_DISABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device1).getPhase());
-        assertEquals(DISPLAY_PHASE_ENABLED,
-                mLogicalDisplayMapper.getDisplayLocked(device2).getPhase());
-    }
-
     /////////////////
     // Helper Methods
     /////////////////
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 7df4b57..077caa4 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1101,6 +1101,10 @@
                 new NotificationChannel("id", "name", IMPORTANCE_HIGH);
         mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
 
+        // pretend only this following part is called by the app (system permissions are required to
+        // update the notification channel on behalf of the user above)
+        mService.isSystemUid = false;
+
         // Recreating with a lower importance leaves channel unchanged.
         final NotificationChannel dupeChannel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
@@ -1126,6 +1130,46 @@
     }
 
     @Test
+    public void testCreateNotificationChannels_fromAppCannotSetFields() throws Exception {
+        // Confirm that when createNotificationChannels is called from the relevant app and not
+        // system, then it cannot set fields that can't be set by apps
+        mService.isSystemUid = false;
+
+        final NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
+        channel.setBypassDnd(true);
+        channel.setAllowBubbles(true);
+
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(channel)));
+
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
+        assertFalse(createdChannel.canBypassDnd());
+        assertFalse(createdChannel.canBubble());
+    }
+
+    @Test
+    public void testCreateNotificationChannels_fromSystemCanSetFields() throws Exception {
+        // Confirm that when createNotificationChannels is called from system,
+        // then it can set fields that can't be set by apps
+        mService.isSystemUid = true;
+
+        final NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
+        channel.setBypassDnd(true);
+        channel.setAllowBubbles(true);
+
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(channel)));
+
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id");
+        assertTrue(createdChannel.canBypassDnd());
+        assertTrue(createdChannel.canBubble());
+    }
+
+    @Test
     public void testBlockedNotifications_suspended() throws Exception {
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
 
@@ -3088,6 +3132,8 @@
 
     @Test
     public void testDeleteChannelGroupChecksForFgses() throws Exception {
+        // the setup for this test requires it to seem like it's coming from the app
+        mService.isSystemUid = false;
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
                 .thenReturn(singletonList(mock(AssociationInfo.class)));
         CountDownLatch latch = new CountDownLatch(2);
@@ -3100,7 +3146,7 @@
             ParceledListSlice<NotificationChannel> pls =
                     new ParceledListSlice(ImmutableList.of(notificationChannel));
             try {
-                mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+                mBinderService.createNotificationChannels(PKG, pls);
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -3119,8 +3165,10 @@
                 ParceledListSlice<NotificationChannel> pls =
                         new ParceledListSlice(ImmutableList.of(notificationChannel));
                 try {
-                mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
-                mBinderService.deleteNotificationChannelGroup(PKG, "group");
+                    // Because existing channels won't have their groups overwritten when the call
+                    // is from the app, this call won't take the channel out of the group
+                    mBinderService.createNotificationChannels(PKG, pls);
+                    mBinderService.deleteNotificationChannelGroup(PKG, "group");
                 } catch (RemoteException e) {
                     throw new RuntimeException(e);
                 }
@@ -7549,6 +7597,65 @@
     }
 
     @Test
+    public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
+        mService.isSystemUid = true;
+        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        mService.setZenHelper(mockZenModeHelper);
+        ComponentName owner = new ComponentName("android", "ProviderName");
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+        boolean isEnabled = true;
+        AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+                zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+        mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+
+        // verify that zen mode helper gets passed in a package name of "android"
+        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString());
+    }
+
+    @Test
+    public void testAddAutomaticZenRule_systemAppIdCallTakesPackageFromOwner() throws Exception {
+        // The multi-user case: where the calling uid doesn't match the system uid, but the calling
+        // *appid* is the system.
+        mService.isSystemUid = false;
+        mService.isSystemAppId = true;
+        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        mService.setZenHelper(mockZenModeHelper);
+        ComponentName owner = new ComponentName("android", "ProviderName");
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+        boolean isEnabled = true;
+        AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+                zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+        mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+
+        // verify that zen mode helper gets passed in a package name of "android"
+        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString());
+    }
+
+    @Test
+    public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
+        mService.isSystemUid = false;
+        mService.isSystemAppId = false;
+        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        mService.setZenHelper(mockZenModeHelper);
+        ComponentName owner = new ComponentName("android", "ProviderName");
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+        boolean isEnabled = true;
+        AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+                zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+        mBinderService.addAutomaticZenRule(rule, "another.package");
+
+        // verify that zen mode helper gets passed in the package name from the arg, not the owner
+        verify(mockZenModeHelper).addAutomaticZenRule(
+                eq("another.package"), eq(rule), anyString());
+    }
+
+    @Test
     public void testAreNotificationsEnabledForPackage() throws Exception {
         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
                 mUid);
@@ -8566,7 +8673,7 @@
         assertEquals("friend", friendChannel.getConversationId());
         assertEquals(null, original.getConversationId());
         assertEquals(original.canShowBadge(), friendChannel.canShowBadge());
-        assertFalse(friendChannel.canBubble()); // can't be modified by app
+        assertEquals(original.canBubble(), friendChannel.canBubble()); // called by system
         assertFalse(original.getId().equals(friendChannel.getId()));
         assertNotNull(friendChannel.getId());
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index 8cf74fb..61a6985 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -32,6 +32,7 @@
 public class TestableNotificationManagerService extends NotificationManagerService {
     int countSystemChecks = 0;
     boolean isSystemUid = true;
+    boolean isSystemAppId = true;
     int countLogSmartSuggestionsVisible = 0;
     Set<Integer> mChannelToastsSent = new HashSet<>();
 
@@ -58,6 +59,12 @@
     }
 
     @Override
+    protected boolean isCallingAppIdSystem() {
+        countSystemChecks++;
+        return isSystemUid || isSystemAppId;
+    }
+
+    @Override
     protected boolean isCallerSystemOrPhone() {
         countSystemChecks++;
         return isSystemUid;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 4550b56..2ccdcaa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1672,6 +1672,36 @@
     }
 
     @Test
+    public void testAddAutomaticZenRule_claimedSystemOwner() {
+        // Make sure anything that claims to have a "system" owner but not actually part of the
+        // system package still gets limited on number of rules
+        for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+            ScheduleInfo si = new ScheduleInfo();
+            si.startHour = i;
+            AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+                    new ComponentName("android", "ScheduleConditionProvider" + i),
+                    null, // configuration activity
+                    ZenModeConfig.toScheduleConditionId(si),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            assertNotNull(id);
+        }
+        try {
+            AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                    new ComponentName("android", "ScheduleConditionProviderFinal"),
+                    null, // configuration activity
+                    ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            fail("allowed too many rules to be created");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+    }
+
+    @Test
     public void testAddAutomaticZenRule_CA() {
         AutomaticZenRule zenRule = new AutomaticZenRule("name",
                 null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8a0a4f7..ff5622f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2809,7 +2809,7 @@
         final Task task = activity.getTask();
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
         topActivity.setVisible(false);
-        task.positionChildAt(topActivity, POSITION_TOP);
+        task.positionChildAt(POSITION_TOP, topActivity, false /* includeParents */);
         activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
                 true, false, false, false);
         waitUntilHandlersIdle();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 496f681..6fe2d2c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1131,6 +1131,26 @@
     }
 
     @Test
+    public void testRecycleTaskWakeUpWhenDreaming() {
+        doNothing().when(mWm.mAtmService.mTaskSupervisor).wakeUp(anyString());
+        doReturn(true).when(mWm.mAtmService).isDreaming();
+        final ActivityStarter starter = prepareStarter(0 /* flags */);
+        final ActivityRecord target = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        starter.mStartActivity = target;
+        target.mVisibleRequested = false;
+        target.setTurnScreenOn(true);
+        // Assume the flag was consumed by relayout.
+        target.setCurrentLaunchCanTurnScreenOn(false);
+        startActivityInner(starter, target, null /* source */, null /* options */,
+                null /* inTask */, null /* inTaskFragment */);
+        // The flag should be set again when resuming (from recycleTask) the target as top.
+        assertTrue(target.currentLaunchCanTurnScreenOn());
+        // In real case, dream activity has a higher priority (TaskDisplayArea#getPriority) that
+        // will be put at a higher z-order. So it relies on wakeUp() to be dismissed.
+        verify(mWm.mAtmService.mTaskSupervisor).wakeUp(anyString());
+    }
+
+    @Test
     public void testTargetTaskInSplitScreen() {
         final ActivityStarter starter =
                 prepareStarter(FLAG_ACTIVITY_LAUNCH_ADJACENT, false /* mockGetRootTask */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 181e81d..06eea29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -25,6 +25,7 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
@@ -69,6 +70,7 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.times;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -84,6 +86,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
+import android.view.InsetsSource;
 import android.view.InsetsVisibilities;
 import android.view.WindowManager;
 
@@ -103,6 +106,9 @@
 import org.junit.Test;
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
 
 /**
  * Tests for Size Compatibility mode.
@@ -2369,6 +2375,48 @@
     }
 
     @Test
+    public void testLetterboxDetailsForTaskBar_letterboxNotOverlappingTaskBar() {
+        mAtm.mDevEnableNonResizableMultiWindow = true;
+        final int screenHeight = 2200;
+        final int screenWidth = 1400;
+        final int taskbarHeight = 200;
+        setUpDisplaySizeWithApp(screenWidth, screenHeight);
+
+        final TestSplitOrganizer organizer =
+                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
+
+        // Move first activity to split screen which takes half of the screen.
+        organizer.mPrimary.setBounds(0, screenHeight / 2, screenWidth, screenHeight);
+        organizer.putTaskToPrimary(mTask, true);
+
+        final InsetsSource navSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR);
+        navSource.setFrame(new Rect(0, screenHeight - taskbarHeight, screenWidth, screenHeight));
+
+        mActivity.mWmService.mLetterboxConfiguration.setLetterboxActivityCornersRadius(15);
+
+        final WindowState w1 = addWindowToActivity(mActivity);
+        w1.mAboveInsetsState.addSource(navSource);
+
+        // Prepare unresizable activity with max aspect ratio
+        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
+
+        // Refresh the letterboxes
+        mActivity.mRootWindowContainer.performSurfacePlacement();
+
+        final ArgumentCaptor<Rect> cropCapturer = ArgumentCaptor.forClass(Rect.class);
+        verify(mTransaction, times(2)).setWindowCrop(
+                eq(w1.getSurfaceControl()),
+                cropCapturer.capture()
+        );
+        final List<Rect> capturedCrops = cropCapturer.getAllValues();
+
+        final int expectedHeight = screenHeight / 2 - taskbarHeight;
+        assertEquals(2, capturedCrops.size());
+        assertEquals(expectedHeight, capturedCrops.get(0).bottom);
+        assertEquals(expectedHeight, capturedCrops.get(1).bottom);
+    }
+
+    @Test
     public void testSplitScreenLetterboxDetailsForStatusBar_twoLetterboxedApps() {
         mAtm.mDevEnableNonResizableMultiWindow = true;
         setUpDisplaySizeWithApp(2800, 1000);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 83f1789..3ff2c0e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -118,10 +118,13 @@
         doReturn(true).when(mTaskFragment).isVisibleRequested();
 
         clearInvocations(mTransaction);
+        mTaskFragment.deferOrganizedTaskFragmentSurfaceUpdate();
         mTaskFragment.setBounds(endBounds);
+        assertTrue(mTaskFragment.shouldStartChangeTransition(startBounds));
+        mTaskFragment.initializeChangeTransition(startBounds);
+        mTaskFragment.continueOrganizedTaskFragmentSurfaceUpdate();
 
         // Surface reset when prepare transition.
-        verify(mTaskFragment).initializeChangeTransition(startBounds);
         verify(mTransaction).setPosition(mLeash, 0, 0);
         verify(mTransaction).setWindowCrop(mLeash, 0, 0);
 
@@ -166,7 +169,7 @@
 
         mTaskFragment.setBounds(endBounds);
 
-        verify(mTaskFragment, never()).initializeChangeTransition(any());
+        assertFalse(mTaskFragment.shouldStartChangeTransition(startBounds));
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 68ac1d6..0c8e89a8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -36,6 +36,7 @@
 import static android.view.Surface.ROTATION_90;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -82,6 +83,7 @@
 import android.util.Xml;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.window.TaskFragmentOrganizer;
 
 import androidx.test.filters.MediumTest;
 
@@ -1469,6 +1471,26 @@
                 tf0, parentTask.getTaskFragment(TaskFragment::isOrganizedTaskFragment));
     }
 
+    @Test
+    public void testReorderActivityToFront() {
+        final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
+        final Task task =  new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+        doNothing().when(task).onActivityVisibleRequestedChanged();
+        final ActivityRecord activity = task.getTopMostActivity();
+
+        final TaskFragment fragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
+        final ActivityRecord embeddedActivity = fragment.getTopMostActivity();
+        task.moveActivityToFront(activity);
+        assertEquals("Activity must be moved to front", activity, task.getTopMostActivity());
+
+        doNothing().when(fragment).sendTaskFragmentInfoChanged();
+        task.moveActivityToFront(embeddedActivity);
+        assertEquals("Activity must be moved to front", embeddedActivity,
+                task.getTopMostActivity());
+        assertEquals("Activity must not be embedded", embeddedActivity,
+                task.getTopChild());
+    }
+
     private Task getTestTask() {
         final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
         return task.getBottomMostTask();
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 24fc93a..8deb282 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1179,7 +1179,7 @@
         assertTrue(rootTask2.isOrganized());
 
         // Verify a back pressed does not call the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+        mWm.mAtmService.mActivityClientController.onBackPressed(activity.token,
                 new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
@@ -1190,7 +1190,7 @@
                 rootTask.mRemoteToken.toWindowContainerToken(), true);
 
         // Verify now that the back press does call the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+        mWm.mAtmService.mActivityClientController.onBackPressed(activity.token,
                 new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
@@ -1201,7 +1201,7 @@
                 rootTask.mRemoteToken.toWindowContainerToken(), false);
 
         // Verify now that the back press no longer calls the organizer
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(activity.token,
+        mWm.mAtmService.mActivityClientController.onBackPressed(activity.token,
                 new IRequestFinishCallback.Default());
         // Ensure events dispatch to organizer.
         mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
@@ -1407,7 +1407,7 @@
         mWm.mWindowPlacerLocked.deferLayout();
 
         rootTask.removeImmediately();
-        mWm.mAtmService.mActivityClientController.onBackPressedOnTaskRoot(record.token,
+        mWm.mAtmService.mActivityClientController.onBackPressed(record.token,
                 new IRequestFinishCallback.Default());
         waitUntilHandlersIdle();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 9bcc136..04d8734 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -95,6 +95,8 @@
 import android.view.InsetsVisibilities;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
+import android.window.ITaskFragmentOrganizer;
+import android.window.TaskFragmentOrganizer;
 
 import androidx.test.filters.SmallTest;
 
@@ -798,6 +800,39 @@
     }
 
     @Test
+    public void testEmbeddedActivityResizing_clearAllDrawn() {
+        final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
+        mAtm.mTaskFragmentOrganizerController.registerOrganizer(
+                ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()));
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment embeddedTf = createTaskFragmentWithEmbeddedActivity(task, organizer);
+        final ActivityRecord embeddedActivity = embeddedTf.getTopMostActivity();
+        final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION, embeddedActivity,
+                "App window");
+        doReturn(true).when(embeddedActivity).isVisible();
+        embeddedActivity.mVisibleRequested = true;
+        makeWindowVisible(win);
+        win.mLayoutSeq = win.getDisplayContent().mLayoutSeq;
+        // Set the bounds twice:
+        // 1. To make sure there is no orientation change after #reportResized, which can also cause
+        // #clearAllDrawn.
+        // 2. Make #isLastConfigReportedToClient to be false after #reportResized, so it can process
+        // to check if we need redraw.
+        embeddedTf.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        embeddedTf.setBounds(0, 0, 1000, 2000);
+        win.reportResized();
+        embeddedTf.setBounds(500, 0, 1000, 2000);
+
+        // Clear all drawn when the embedded TaskFragment is in mDisplayContent.mChangingContainers.
+        win.updateResizingWindowIfNeeded();
+        verify(embeddedActivity, never()).clearAllDrawn();
+
+        mDisplayContent.mChangingContainers.add(embeddedTf);
+        win.updateResizingWindowIfNeeded();
+        verify(embeddedActivity).clearAllDrawn();
+    }
+
+    @Test
     public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
         final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
         win0.mActivityRecord.mVisibleRequested = false;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java
new file mode 100644
index 0000000..d5eea1f
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.voiceinteraction;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+
+import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.media.permission.Identity;
+import android.os.ParcelFileDescriptor;
+import android.service.voice.HotwordAudioStream;
+import android.service.voice.HotwordDetectedResult;
+import android.util.Pair;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+final class HotwordAudioStreamManager {
+
+    private static final String TAG = "HotwordAudioStreamManager";
+    private static final String OP_MESSAGE = "Streaming hotword audio to VoiceInteractionService";
+    private static final String TASK_ID_PREFIX = "HotwordDetectedResult@";
+    private static final String THREAD_NAME_PREFIX = "Copy-";
+
+    private final AppOpsManager mAppOpsManager;
+    private final Identity mVoiceInteractorIdentity;
+    private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
+
+    HotwordAudioStreamManager(@NonNull AppOpsManager appOpsManager,
+            @NonNull Identity voiceInteractorIdentity) {
+        mAppOpsManager = appOpsManager;
+        mVoiceInteractorIdentity = voiceInteractorIdentity;
+    }
+
+    /**
+     * Starts copying the audio streams in the given {@link HotwordDetectedResult}.
+     * <p>
+     * The returned {@link HotwordDetectedResult} is identical the one that was passed in, except
+     * that the {@link ParcelFileDescriptor}s within {@link HotwordDetectedResult#getAudioStreams()}
+     * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamManager}. The
+     * returned value should be passed on to the client (i.e., the voice interactor).
+     * </p>
+     *
+     * @throws IOException If there was an error creating the managed pipe.
+     */
+    @NonNull
+    public HotwordDetectedResult startCopyingAudioStreams(@NonNull HotwordDetectedResult result)
+            throws IOException {
+        List<HotwordAudioStream> audioStreams = result.getAudioStreams();
+        if (audioStreams.isEmpty()) {
+            return result;
+        }
+
+        List<HotwordAudioStream> newAudioStreams = new ArrayList<>(audioStreams.size());
+        List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> sourcesAndSinks = new ArrayList<>(
+                audioStreams.size());
+        for (HotwordAudioStream audioStream : audioStreams) {
+            ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe();
+            ParcelFileDescriptor clientAudioSource = clientPipe[0];
+            ParcelFileDescriptor clientAudioSink = clientPipe[1];
+            HotwordAudioStream newAudioStream =
+                    audioStream.buildUpon().setAudioStreamParcelFileDescriptor(
+                            clientAudioSource).build();
+            newAudioStreams.add(newAudioStream);
+
+            ParcelFileDescriptor serviceAudioSource =
+                    audioStream.getAudioStreamParcelFileDescriptor();
+            sourcesAndSinks.add(new Pair<>(serviceAudioSource, clientAudioSink));
+        }
+
+        String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result);
+        mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, sourcesAndSinks));
+
+        return result.buildUpon().setAudioStreams(newAudioStreams).build();
+    }
+
+    private class HotwordDetectedResultCopyTask implements Runnable {
+        private final String mResultTaskId;
+        private final List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> mSourcesAndSinks;
+        private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
+
+        HotwordDetectedResultCopyTask(String resultTaskId,
+                List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> sourcesAndSinks) {
+            mResultTaskId = resultTaskId;
+            mSourcesAndSinks = sourcesAndSinks;
+        }
+
+        @Override
+        public void run() {
+            Thread.currentThread().setName(THREAD_NAME_PREFIX + mResultTaskId);
+            int size = mSourcesAndSinks.size();
+            List<SingleAudioStreamCopyTask> tasks = new ArrayList<>(size);
+            for (int i = 0; i < size; i++) {
+                Pair<ParcelFileDescriptor, ParcelFileDescriptor> sourceAndSink =
+                        mSourcesAndSinks.get(i);
+                ParcelFileDescriptor serviceAudioSource = sourceAndSink.first;
+                ParcelFileDescriptor clientAudioSink = sourceAndSink.second;
+                String streamTaskId = mResultTaskId + "@" + i;
+                tasks.add(new SingleAudioStreamCopyTask(streamTaskId, serviceAudioSource,
+                        clientAudioSink));
+            }
+
+            if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD,
+                    mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
+                    mVoiceInteractorIdentity.attributionTag, OP_MESSAGE) == MODE_ALLOWED) {
+                try {
+                    // TODO(b/244599891): Set timeout, close after inactivity
+                    mExecutorService.invokeAll(tasks);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, mResultTaskId + ": Task was interrupted", e);
+                    bestEffortPropagateError(e.getMessage());
+                } finally {
+                    mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD,
+                            mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
+                            mVoiceInteractorIdentity.attributionTag);
+                }
+            } else {
+                bestEffortPropagateError(
+                        "Failed to obtain RECORD_AUDIO_HOTWORD permission for "
+                                + SoundTriggerSessionPermissionsDecorator.toString(
+                                mVoiceInteractorIdentity));
+            }
+        }
+
+        private void bestEffortPropagateError(@NonNull String errorMessage) {
+            try {
+                for (Pair<ParcelFileDescriptor, ParcelFileDescriptor> sourceAndSink :
+                        mSourcesAndSinks) {
+                    ParcelFileDescriptor serviceAudioSource = sourceAndSink.first;
+                    ParcelFileDescriptor clientAudioSink = sourceAndSink.second;
+                    serviceAudioSource.closeWithError(errorMessage);
+                    clientAudioSink.closeWithError(errorMessage);
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e);
+            }
+        }
+    }
+
+    private static class SingleAudioStreamCopyTask implements Callable<Void> {
+        // TODO: Make this buffer size customizable from updateState()
+        private static final int COPY_BUFFER_LENGTH = 2_560;
+
+        private final String mStreamTaskId;
+        private final ParcelFileDescriptor mAudioSource;
+        private final ParcelFileDescriptor mAudioSink;
+
+        SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource,
+                ParcelFileDescriptor audioSink) {
+            mStreamTaskId = streamTaskId;
+            mAudioSource = audioSource;
+            mAudioSink = audioSink;
+        }
+
+        @Override
+        public Void call() throws Exception {
+            Thread.currentThread().setName(THREAD_NAME_PREFIX + mStreamTaskId);
+
+            // Note: We are intentionally NOT using try-with-resources here. If we did,
+            // the ParcelFileDescriptors will be automatically closed WITHOUT errors before we go
+            // into the IOException-catch block. We want to propagate the error while closing the
+            // PFDs.
+            InputStream fis = null;
+            OutputStream fos = null;
+            try {
+                fis = new ParcelFileDescriptor.AutoCloseInputStream(mAudioSource);
+                fos = new ParcelFileDescriptor.AutoCloseOutputStream(mAudioSink);
+                byte[] buffer = new byte[COPY_BUFFER_LENGTH];
+                while (true) {
+                    if (Thread.interrupted()) {
+                        Slog.e(TAG,
+                                mStreamTaskId + ": SingleAudioStreamCopyTask task was interrupted");
+                        break;
+                    }
+
+                    int bytesRead = fis.read(buffer);
+                    if (bytesRead < 0) {
+                        Slog.i(TAG, mStreamTaskId + ": Reached end of audio stream");
+                        break;
+                    }
+                    if (bytesRead > 0) {
+                        if (DEBUG) {
+                            // TODO(b/244599440): Add proper logging
+                            Slog.d(TAG, mStreamTaskId + ": Copied " + bytesRead
+                                    + " bytes from audio stream. First 20 bytes=" + Arrays.toString(
+                                    Arrays.copyOfRange(buffer, 0, 20)));
+                        }
+                        fos.write(buffer, 0, bytesRead);
+                    }
+                    // TODO(b/244599891): Close PFDs after inactivity
+                }
+            } catch (IOException e) {
+                mAudioSource.closeWithError(e.getMessage());
+                mAudioSink.closeWithError(e.getMessage());
+                Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e);
+            } finally {
+                if (fis != null) {
+                    fis.close();
+                }
+                if (fos != null) {
+                    fos.close();
+                }
+            }
+
+            return null;
+        }
+    }
+
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index a6e1a32..6f7d80c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -19,7 +19,6 @@
 import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
 import static android.Manifest.permission.RECORD_AUDIO;
 import static android.service.attention.AttentionService.PROXIMITY_UNKNOWN;
-import static android.service.voice.HotwordDetectedResult.EXTRA_PROXIMITY_METERS;
 import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_EXTERNAL;
 import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPHONE;
 import static android.service.voice.HotwordDetectionService.ENABLE_PROXIMITY_RESULT;
@@ -59,6 +58,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.AppOpsManager;
 import android.attention.AttentionManagerInternal;
 import android.content.ComponentName;
 import android.content.ContentCaptureOptions;
@@ -137,6 +137,7 @@
     // The error codes are used for onError callback
     private static final int HOTWORD_DETECTION_SERVICE_DIED = -1;
     private static final int CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION = -2;
+    private static final int CALLBACK_ONDETECTED_STREAM_COPY_ERROR = -4;
 
     // Hotword metrics
     private static final int METRICS_INIT_UNKNOWN_TIMEOUT =
@@ -168,6 +169,8 @@
     // TODO: This may need to be a Handler(looper)
     private final ScheduledExecutorService mScheduledExecutorService =
             Executors.newSingleThreadScheduledExecutor();
+    private final AppOpsManager mAppOpsManager;
+    private final HotwordAudioStreamManager mHotwordAudioStreamManager;
     @Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
     private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
     private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
@@ -189,7 +192,7 @@
     @Nullable AttentionManagerInternal mAttentionManagerInternal = null;
 
     final AttentionManagerInternal.ProximityUpdateCallbackInternal mProximityCallbackInternal =
-            this::setProximityMeters;
+            this::setProximityValue;
 
 
     volatile HotwordDetectionServiceIdentity mIdentity;
@@ -228,6 +231,9 @@
         mContext = context;
         mVoiceInteractionServiceUid = voiceInteractionServiceUid;
         mVoiceInteractorIdentity = voiceInteractorIdentity;
+        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+        mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager,
+                mVoiceInteractorIdentity);
         mDetectionComponentName = serviceName;
         mUser = userId;
         mCallback = callback;
@@ -481,14 +487,20 @@
                         mSoftwareCallback.onError();
                         return;
                     }
-                    saveProximityMetersToBundle(result);
-                    mSoftwareCallback.onDetected(result, null, null);
-                    if (result != null) {
-                        Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
-                                + " bits from hotword trusted process");
-                        if (mDebugHotwordLogging) {
-                            Slog.i(TAG, "Egressed detected result: " + result);
-                        }
+                    saveProximityValueToBundle(result);
+                    HotwordDetectedResult newResult;
+                    try {
+                        newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result);
+                    } catch (IOException e) {
+                        // TODO: Write event
+                        mSoftwareCallback.onError();
+                        return;
+                    }
+                    mSoftwareCallback.onDetected(newResult, null, null);
+                    Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+                            + " bits from hotword trusted process");
+                    if (mDebugHotwordLogging) {
+                        Slog.i(TAG, "Egressed detected result: " + newResult);
                     }
                 }
             }
@@ -586,7 +598,7 @@
                         externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
                         return;
                     }
-                    saveProximityMetersToBundle(result);
+                    saveProximityValueToBundle(result);
                     externalCallback.onKeyphraseDetected(recognitionEvent, result);
                     if (result != null) {
                         Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
@@ -660,20 +672,27 @@
                     try {
                         enforcePermissionsForDataDelivery();
                     } catch (SecurityException e) {
+                        Slog.i(TAG, "Ignoring #onDetected due to a SecurityException", e);
                         HotwordMetricsLogger.writeKeyphraseTriggerEvent(
                                 mDetectorType,
                                 METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION);
                         externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
                         return;
                     }
-                    saveProximityMetersToBundle(result);
-                    externalCallback.onKeyphraseDetected(recognitionEvent, result);
-                    if (result != null) {
-                        Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
-                                + " bits from hotword trusted process");
-                        if (mDebugHotwordLogging) {
-                            Slog.i(TAG, "Egressed detected result: " + result);
-                        }
+                    saveProximityValueToBundle(result);
+                    HotwordDetectedResult newResult;
+                    try {
+                        newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result);
+                    } catch (IOException e) {
+                        // TODO: Write event
+                        externalCallback.onError(CALLBACK_ONDETECTED_STREAM_COPY_ERROR);
+                        return;
+                    }
+                    externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
+                    Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+                            + " bits from hotword trusted process");
+                    if (mDebugHotwordLogging) {
+                        Slog.i(TAG, "Egressed detected result: " + newResult);
                     }
                 }
             }
@@ -757,6 +776,7 @@
     }
 
     private void restartProcessLocked() {
+        // TODO(b/244598068): Check HotwordAudioStreamManager first
         Slog.v(TAG, "Restarting hotword detection process");
         ServiceConnection oldConnection = mRemoteHotwordDetectionService;
         HotwordDetectionServiceIdentity previousIdentity = mIdentity;
@@ -991,16 +1011,24 @@
                                         callback.onError();
                                         return;
                                     }
-                                    callback.onDetected(triggerResult, null /* audioFormat */,
+                                    HotwordDetectedResult newResult;
+                                    try {
+                                        newResult =
+                                                mHotwordAudioStreamManager.startCopyingAudioStreams(
+                                                        triggerResult);
+                                    } catch (IOException e) {
+                                        // TODO: Write event
+                                        callback.onError();
+                                        return;
+                                    }
+                                    callback.onDetected(newResult, null /* audioFormat */,
                                             null /* audioStream */);
-                                    if (triggerResult != null) {
-                                        Slog.i(TAG, "Egressed "
-                                                + HotwordDetectedResult.getUsageSize(triggerResult)
-                                                + " bits from hotword trusted process");
-                                        if (mDebugHotwordLogging) {
-                                            Slog.i(TAG,
-                                                    "Egressed detected result: " + triggerResult);
-                                        }
+                                    Slog.i(TAG, "Egressed "
+                                            + HotwordDetectedResult.getUsageSize(newResult)
+                                            + " bits from hotword trusted process");
+                                    if (mDebugHotwordLogging) {
+                                        Slog.i(TAG,
+                                                "Egressed detected result: " + newResult);
                                     }
                                 }
                             });
@@ -1215,15 +1243,15 @@
         });
     }
 
-    private void saveProximityMetersToBundle(HotwordDetectedResult result) {
+    private void saveProximityValueToBundle(HotwordDetectedResult result) {
         synchronized (mLock) {
             if (result != null && mProximityMeters != PROXIMITY_UNKNOWN) {
-                result.getExtras().putDouble(EXTRA_PROXIMITY_METERS, mProximityMeters);
+                result.setProximity(mProximityMeters);
             }
         }
     }
 
-    private void setProximityMeters(double proximityMeters) {
+    private void setProximityValue(double proximityMeters) {
         synchronized (mLock) {
             mProximityMeters = proximityMeters;
         }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index cf6d681..83bc0fc0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1180,7 +1180,10 @@
             "carrier_data_call_retry_network_requested_max_count_int";
 
     /**
-     * Data call setup permanent failure causes by the carrier
+     * Data call setup permanent failure causes by the carrier.
+     *
+     * This API key was added in mistake and is not used anymore by the telephony data
+     * frameworks.
      */
     public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS =
             "carrier_data_call_permanent_failure_strings";
@@ -8308,7 +8311,8 @@
      *
      * The syntax of the retry rule:
      * 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities
-     *    are supported.
+     *    are supported. If the capabilities are not specified, then the retry rule only applies
+     *    to the current failed APN used in setup data call request.
      * "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
      *
      * 2. Retry based on {@link DataFailCause}
@@ -8319,15 +8323,16 @@
      * "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...],
      *     [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
      *
+     * 4. Permanent fail causes (no timer-based retry) on the current failed APN. Retry interval
+     *    is specified for retrying the next available APN.
+     * "permanent_fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|65543|65547|
+     *     2252|2253|2254, retry_interval=2500"
+     *
      * For example,
      * "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached
      * network request is emergency, then retry data network setup every 1 second for up to 20
      * times.
      *
-     * "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|2254
-     * , maximum_retries=0" means for those fail causes, never retry with timers. Note that
-     * when environment changes, retry can still happen.
-     *
      * "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
      * "5000|10000|15000|20000|40000|60000|120000|240000|600000|1200000|1800000"
      * "1800000, maximum_retries=20" means for those capabilities, retry happens in 2.5s, 3s, 5s,
@@ -9205,8 +9210,13 @@
         sDefaults.putStringArray(
                 KEY_TELEPHONY_DATA_SETUP_RETRY_RULES_STRING_ARRAY, new String[] {
                         "capabilities=eims, retry_interval=1000, maximum_retries=20",
-                        "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2252|"
-                                + "2253|2254, maximum_retries=0", // No retry for those causes
+                        // Permanent fail causes. When setup data call fails with the following
+                        // fail causes, telephony data frameworks will stop timer-based retry on
+                        // the failed APN until power cycle, APM, or some special events. Note that
+                        // even though timer-based retry is not performed, condition-based (RAT
+                        // changes, registration state changes) retry can still happen.
+                        "permanent_fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|"
+                                + "-3|65543|65547|2252|2253|2254, retry_interval=2500",
                         "capabilities=mms|supl|cbs, retry_interval=2000",
                         "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
                                 + "5000|10000|15000|20000|40000|60000|120000|240000|"
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 06cfd67..6e3cfac 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -107,7 +107,7 @@
 
         if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
             AnomalyReporter.reportAnomaly(
-                    UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
+                    UUID.fromString("e257ae06-ac0a-44c0-ba63-823b9f07b3e4"),
                     "CellIdentity Missing Half of PLMN ID");
         }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b6f8652..ecd8c7a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12273,7 +12273,7 @@
             Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
         } catch (NullPointerException e) {
             AnomalyReporter.reportAnomaly(
-                    UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
+                    UUID.fromString("e2bed88e-def9-476e-bd71-3e572a8de6d1"),
                     "getServiceStateForSubscriber " + subId + " NPE");
         }
         return null;
@@ -15380,11 +15380,28 @@
     public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2;
 
     /**
+     * Allow switching mobile data to the non-default SIM if the non-default SIM has better
+     * availability.
+     *
+     * This is used for temporarily allowing data on the non-default data SIM when on-default SIM
+     * has better availability on DSDS devices, where better availability means strong
+     * signal/connectivity.
+     * If this policy is enabled, data will be temporarily enabled on the non-default data SIM,
+     * including during any voice calls(equivalent to enabling
+     * {@link #MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL}).
+     *
+     * This policy can be enabled and disabled via {@link #setMobileDataPolicyEnabled}.
+     * @hide
+     */
+    public static final int MOBILE_DATA_POLICY_AUTO_DATA_SWITCH = 3;
+
+    /**
      * @hide
      */
     @IntDef(prefix = { "MOBILE_DATA_POLICY_" }, value = {
             MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
             MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
+            MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface MobileDataPolicy { }
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 73aff43..a834e2bb 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -468,14 +468,14 @@
         final boolean isQosBearerSessionsSame =
                 (mQosBearerSessions == null || other.mQosBearerSessions == null)
                 ? mQosBearerSessions == other.mQosBearerSessions
-                : mQosBearerSessions.size() == other.mQosBearerSessions.size()
-                && mQosBearerSessions.containsAll(other.mQosBearerSessions);
+                : (mQosBearerSessions.size() == other.mQosBearerSessions.size()
+                        && mQosBearerSessions.containsAll(other.mQosBearerSessions));
 
         final boolean isTrafficDescriptorsSame =
                 (mTrafficDescriptors == null || other.mTrafficDescriptors == null)
                 ? mTrafficDescriptors == other.mTrafficDescriptors
-                : mTrafficDescriptors.size() == other.mTrafficDescriptors.size()
-                && mTrafficDescriptors.containsAll(other.mTrafficDescriptors);
+                : (mTrafficDescriptors.size() == other.mTrafficDescriptors.size()
+                        && mTrafficDescriptors.containsAll(other.mTrafficDescriptors));
 
         return mCause == other.mCause
                 && mSuggestedRetryTime == other.mSuggestedRetryTime
@@ -504,10 +504,35 @@
 
     @Override
     public int hashCode() {
+        // Generate order-independent hashes for lists
+        int addressesHash = mAddresses.stream()
+                .map(LinkAddress::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
+        int dnsAddressesHash = mDnsAddresses.stream()
+                .map(InetAddress::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
+        int gatewayAddressesHash = mGatewayAddresses.stream()
+                .map(InetAddress::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
+        int pcscfAddressesHash = mPcscfAddresses.stream()
+                .map(InetAddress::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
+        int qosBearerSessionsHash = mQosBearerSessions.stream()
+                .map(QosBearerSession::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
+        int trafficDescriptorsHash = mTrafficDescriptors.stream()
+                .map(TrafficDescriptor::hashCode)
+                .mapToInt(Integer::intValue)
+                .sum();
         return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
-                mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
-                mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
-                mQosBearerSessions, mSliceInfo, mTrafficDescriptors);
+                mInterfaceName, addressesHash, dnsAddressesHash, gatewayAddressesHash,
+                pcscfAddressesHash, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
+                mDefaultQos, qosBearerSessionsHash, mSliceInfo, trafficDescriptorsHash);
     }
 
     @Override
@@ -816,8 +841,8 @@
         /**
          * Set pdu session id.
          * <p/>
-         * The id must be between 1 and 15 when linked to a pdu session.  If no pdu session
-         * exists for the current data call, the id must be set to {@link PDU_SESSION_ID_NOT_SET}.
+         * The id must be between 1 and 15 when linked to a pdu session. If no pdu session
+         * exists for the current data call, the id must be set to {@link #PDU_SESSION_ID_NOT_SET}.
          *
          * @param pduSessionId Pdu Session Id of the data call.
          * @return The same instance of the builder.
@@ -858,6 +883,7 @@
          */
         public @NonNull Builder setQosBearerSessions(
                 @NonNull List<QosBearerSession> qosBearerSessions) {
+            Objects.requireNonNull(qosBearerSessions);
             mQosBearerSessions = qosBearerSessions;
             return this;
         }
@@ -891,6 +917,7 @@
          */
         public @NonNull Builder setTrafficDescriptors(
                 @NonNull List<TrafficDescriptor> trafficDescriptors) {
+            Objects.requireNonNull(trafficDescriptors);
             mTrafficDescriptors = trafficDescriptors;
             return this;
         }