Merge "Fix SettingsProvider for use_resource_processor: true" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index c8046ab..db51537 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -17,7 +17,9 @@
     ":android.companion.flags-aconfig-java{.generated_srcjars}",
     ":android.content.pm.flags-aconfig-java{.generated_srcjars}",
     ":android.content.res.flags-aconfig-java{.generated_srcjars}",
+    ":android.hardware.flags-aconfig-java{.generated_srcjars}",
     ":android.hardware.radio.flags-aconfig-java{.generated_srcjars}",
+    ":android.location.flags-aconfig-java{.generated_srcjars}",
     ":android.nfc.flags-aconfig-java{.generated_srcjars}",
     ":android.os.flags-aconfig-java{.generated_srcjars}",
     ":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
@@ -142,6 +144,21 @@
     aconfig_declarations: "com.android.text.flags-aconfig",
 }
 
+// Location
+aconfig_declarations {
+    name: "android.location.flags-aconfig",
+    package: "android.location.flags",
+    srcs: [
+        "location/java/android/location/flags/*.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "android.location.flags-aconfig-java",
+    aconfig_declarations: "android.location.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // NFC
 aconfig_declarations {
     name: "android.nfc.flags-aconfig",
@@ -281,6 +298,19 @@
     aconfig_declarations: "android.view.accessibility.flags-aconfig",
 }
 
+// Hardware
+aconfig_declarations {
+    name: "android.hardware.flags-aconfig",
+    package: "android.hardware.flags",
+    srcs: ["core/java/android/hardware/flags/*.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.hardware.flags-aconfig-java",
+    aconfig_declarations: "android.hardware.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Widget
 aconfig_declarations {
     name: "android.widget.flags-aconfig",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 015487d..b42f7bc 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -28,3 +28,6 @@
 ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/ktfmt_includes.txt ${PREUPLOAD_FILES}
 
 ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --no-verify-format -f ${PREUPLOAD_FILES}
+
+# This flag check hook runs only for "packages/SystemUI" subdirectory. If you want to include this check for other subdirectories, please modify flag_check.py.
+flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index a143d6f..bbe1485 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1555,7 +1555,7 @@
 
     private final Predicate<Integer> mIsUidActivePredicate = this::isUidActive;
 
-    public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
+    public int scheduleAsPackage(JobInfo job, JobWorkItem work, int callingUid, String packageName,
             int userId, @Nullable String namespace, String tag) {
         // Rate limit excessive schedule() calls.
         final String servicePkg = job.getService().getPackageName();
@@ -1608,12 +1608,12 @@
             mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG);
         }
 
-        if (mActivityManagerInternal.isAppStartModeDisabled(uId, servicePkg)) {
-            Slog.w(TAG, "Not scheduling job " + uId + ":" + job.toString()
+        if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, servicePkg)) {
+            Slog.w(TAG, "Not scheduling job for " + callingUid + ":" + job.toString()
                     + " -- package not allowed to start");
             Counter.logIncrementWithUid(
                     "job_scheduler.value_cntr_w_uid_schedule_failure_app_start_mode_disabled",
-                    uId);
+                    callingUid);
             return JobScheduler.RESULT_FAILURE;
         }
 
@@ -1623,7 +1623,7 @@
                             job.getEstimatedNetworkDownloadBytes()));
             sInitialJobEstimatedNetworkUploadKBLogger.logSample(
                     safelyScaleBytesToKBForHistogram(job.getEstimatedNetworkUploadBytes()));
-            sJobMinimumChunkKBLogger.logSampleWithUid(uId,
+            sJobMinimumChunkKBLogger.logSampleWithUid(callingUid,
                     safelyScaleBytesToKBForHistogram(job.getMinimumNetworkChunkBytes()));
             if (work != null) {
                 sInitialJwiEstimatedNetworkDownloadKBLogger.logSample(
@@ -1632,7 +1632,7 @@
                 sInitialJwiEstimatedNetworkUploadKBLogger.logSample(
                         safelyScaleBytesToKBForHistogram(
                                 work.getEstimatedNetworkUploadBytes()));
-                sJwiMinimumChunkKBLogger.logSampleWithUid(uId,
+                sJwiMinimumChunkKBLogger.logSampleWithUid(callingUid,
                         safelyScaleBytesToKBForHistogram(
                                 work.getMinimumNetworkChunkBytes()));
             }
@@ -1640,11 +1640,12 @@
 
         if (work != null) {
             Counter.logIncrementWithUid(
-                    "job_scheduler.value_cntr_w_uid_job_work_items_enqueued", uId);
+                    "job_scheduler.value_cntr_w_uid_job_work_items_enqueued", callingUid);
         }
 
         synchronized (mLock) {
-            final JobStatus toCancel = mJobs.getJobByUidAndJobId(uId, namespace, job.getId());
+            final JobStatus toCancel =
+                    mJobs.getJobByUidAndJobId(callingUid, namespace, job.getId());
 
             if (work != null && toCancel != null) {
                 // Fast path: we are adding work to an existing job, and the JobInfo is not
@@ -1664,7 +1665,7 @@
                     // TODO(273758274): improve JobScheduler's resilience and memory management
                     if (toCancel.getWorkCount() >= mConstants.MAX_NUM_PERSISTED_JOB_WORK_ITEMS
                             && toCancel.isPersisted()) {
-                        Slog.w(TAG, "Too many JWIs for uid " + uId);
+                        Slog.w(TAG, "Too many JWIs for uid " + callingUid);
                         throw new IllegalStateException("Apps may not persist more than "
                                 + mConstants.MAX_NUM_PERSISTED_JOB_WORK_ITEMS
                                 + " JobWorkItems per job");
@@ -1682,7 +1683,8 @@
                                         | JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
                     }
                     mJobs.touchJob(toCancel);
-                    sEnqueuedJwiHighWaterMarkLogger.logSampleWithUid(uId, toCancel.getWorkCount());
+                    sEnqueuedJwiHighWaterMarkLogger
+                            .logSampleWithUid(callingUid, toCancel.getWorkCount());
 
                     // If any of work item is enqueued when the source is in the foreground,
                     // exempt the entire job.
@@ -1692,8 +1694,8 @@
                 }
             }
 
-            JobStatus jobStatus =
-                    JobStatus.createFromJobInfo(job, uId, packageName, userId, namespace, tag);
+            JobStatus jobStatus = JobStatus.createFromJobInfo(
+                    job, callingUid, packageName, userId, namespace, tag);
 
             // Return failure early if expedited job quota used up.
             if (jobStatus.isRequestedExpeditedJob()) {
@@ -1702,7 +1704,7 @@
                         && !mQuotaController.isWithinEJQuotaLocked(jobStatus))) {
                     Counter.logIncrementWithUid(
                             "job_scheduler.value_cntr_w_uid_schedule_failure_ej_out_of_quota",
-                            uId);
+                            callingUid);
                     return JobScheduler.RESULT_FAILURE;
                 }
             }
@@ -1716,10 +1718,10 @@
             if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
             // Jobs on behalf of others don't apply to the per-app job cap
             if (packageName == null) {
-                if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
-                    Slog.w(TAG, "Too many jobs for uid " + uId);
+                if (mJobs.countJobsForUid(callingUid) > MAX_JOBS_PER_APP) {
+                    Slog.w(TAG, "Too many jobs for uid " + callingUid);
                     Counter.logIncrementWithUid(
-                            "job_scheduler.value_cntr_w_uid_max_scheduling_limit_hit", uId);
+                            "job_scheduler.value_cntr_w_uid_max_scheduling_limit_hit", callingUid);
                     throw new IllegalStateException("Apps may not schedule more than "
                             + MAX_JOBS_PER_APP + " distinct jobs");
                 }
@@ -1743,7 +1745,7 @@
                 // TODO(273758274): improve JobScheduler's resilience and memory management
                 if (work != null && toCancel.isPersisted()
                         && toCancel.getWorkCount() >= mConstants.MAX_NUM_PERSISTED_JOB_WORK_ITEMS) {
-                    Slog.w(TAG, "Too many JWIs for uid " + uId);
+                    Slog.w(TAG, "Too many JWIs for uid " + callingUid);
                     throw new IllegalStateException("Apps may not persist more than "
                             + mConstants.MAX_NUM_PERSISTED_JOB_WORK_ITEMS
                             + " JobWorkItems per job");
@@ -1759,13 +1761,14 @@
             if (work != null) {
                 // If work has been supplied, enqueue it into the new job.
                 jobStatus.enqueueWorkLocked(work);
-                sEnqueuedJwiHighWaterMarkLogger.logSampleWithUid(uId, jobStatus.getWorkCount());
+                sEnqueuedJwiHighWaterMarkLogger
+                        .logSampleWithUid(callingUid, jobStatus.getWorkCount());
             }
 
-            final int sourceUid = uId;
+            final int sourceUid = jobStatus.getSourceUid();
             FrameworkStatsLog.write(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
                     jobStatus.isProxyJob()
-                            ? new int[]{sourceUid, jobStatus.getUid()} : new int[]{sourceUid},
+                            ? new int[]{sourceUid, callingUid} : new int[]{sourceUid},
                     // Given that the source tag is set by the calling app, it should be connected
                     // to the calling app in the attribution for a proxied job.
                     jobStatus.isProxyJob()
diff --git a/cmds/svc/src/com/android/commands/svc/NfcCommand.java b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
index 020ca33..ee2af12 100644
--- a/cmds/svc/src/com/android/commands/svc/NfcCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
@@ -16,10 +16,11 @@
 
 package com.android.commands.svc;
 
+import android.app.ActivityThread;
 import android.content.Context;
-import android.nfc.INfcAdapter;
-import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
+import android.os.Looper;
 
 public class NfcCommand extends Svc.Command {
 
@@ -42,27 +43,26 @@
 
     @Override
     public void run(String[] args) {
-        INfcAdapter adapter = INfcAdapter.Stub.asInterface(
-                ServiceManager.getService(Context.NFC_SERVICE));
-
+        Looper.prepareMainLooper();
+        ActivityThread.initializeMainlineModules();
+        Context context = ActivityThread.systemMain().getSystemContext();
+        NfcManager nfcManager = context.getSystemService(NfcManager.class);
+        if (nfcManager == null) {
+            System.err.println("Got a null NfcManager, is the system running?");
+            return;
+        }
+        NfcAdapter adapter = nfcManager.getDefaultAdapter();
         if (adapter == null) {
             System.err.println("Got a null NfcAdapter, is the system running?");
             return;
         }
-
-        try {
-            if (args.length == 2 && "enable".equals(args[1])) {
-                adapter.enable();
-                return;
-            } else if (args.length == 2 && "disable".equals(args[1])) {
-                adapter.disable(true);
-                return;
-            }
-        } catch (RemoteException e) {
-            System.err.println("NFC operation failed: " + e);
+        if (args.length == 2 && "enable".equals(args[1])) {
+            adapter.enable();
+            return;
+        } else if (args.length == 2 && "disable".equals(args[1])) {
+            adapter.disable(true);
             return;
         }
-
         System.err.println(longHelp());
     }
 
diff --git a/cmds/svc/src/com/android/commands/svc/OWNERS b/cmds/svc/src/com/android/commands/svc/OWNERS
new file mode 100644
index 0000000..d5a5d7b
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48448
+per-file NfcCommand.java = file:platform/packages/apps/Nfc:/OWNERS
diff --git a/core/api/current.txt b/core/api/current.txt
index 7d5417d..d8ea721 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16259,6 +16259,8 @@
 
   public static class Paint.FontMetricsInt {
     ctor public Paint.FontMetricsInt();
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetricsInt);
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetrics);
     field public int ascent;
     field public int bottom;
     field public int descent;
@@ -17577,7 +17579,7 @@
     ctor public FontFamily.Builder(@NonNull android.graphics.fonts.Font);
     method @NonNull public android.graphics.fonts.FontFamily.Builder addFont(@NonNull android.graphics.fonts.Font);
     method @NonNull public android.graphics.fonts.FontFamily build();
-    method @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") @Nullable public android.graphics.fonts.FontFamily buildVariableFamily();
+    method @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") @Nullable public android.graphics.fonts.FontFamily buildVariableFamily();
   }
 
   public final class FontStyle {
@@ -17765,18 +17767,18 @@
     method public float getAdvance();
     method public float getAscent();
     method public float getDescent();
-    method @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") public boolean getFakeBold(@IntRange(from=0) int);
-    method @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") public boolean getFakeItalic(@IntRange(from=0) int);
+    method @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") public boolean getFakeBold(@IntRange(from=0) int);
+    method @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") public boolean getFakeItalic(@IntRange(from=0) int);
     method @NonNull public android.graphics.fonts.Font getFont(@IntRange(from=0) int);
     method @IntRange(from=0) public int getGlyphId(@IntRange(from=0) int);
     method public float getGlyphX(@IntRange(from=0) int);
     method public float getGlyphY(@IntRange(from=0) int);
-    method @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") public float getItalicOverride(@IntRange(from=0) int);
+    method @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") public float getItalicOverride(@IntRange(from=0) int);
     method public float getOffsetX();
     method public float getOffsetY();
-    method @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") public float getWeightOverride(@IntRange(from=0) int);
+    method @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") public float getWeightOverride(@IntRange(from=0) int);
     method @IntRange(from=0) public int glyphCount();
-    field @FlaggedApi("com.android.text.flags.deprecate_fonts_xml") public static final float NO_OVERRIDE = 1.4E-45f;
+    field @FlaggedApi("com.android.text.flags.new_fonts_fallback_xml") public static final float NO_OVERRIDE = 1.4E-45f;
   }
 
   public class TextRunShaper {
@@ -18173,6 +18175,13 @@
     field public static final int YCBCR_P010 = 54; // 0x36
   }
 
+  @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public final class OverlayProperties implements android.os.Parcelable {
+    method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public int describeContents();
+    method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean supportMixedColorSpaces();
+    method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @FlaggedApi("android.hardware.flags.overlayproperties_class_api") @NonNull public static final android.os.Parcelable.Creator<android.hardware.OverlayProperties> CREATOR;
+  }
+
   public final class Sensor {
     method public int getFifoMaxEventCount();
     method public int getFifoReservedEventCount();
@@ -23981,7 +23990,7 @@
     method @NonNull public android.media.MediaRouter2.RoutingController getSystemController();
     method public void registerControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.ControllerCallback);
     method public void registerRouteCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.RouteCallback, @NonNull android.media.RouteDiscoveryPreference);
-    method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public void registerRouteListingPreferenceCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.RouteListingPreferenceCallback);
+    method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public void registerRouteListingPreferenceUpdatedCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.media.RouteListingPreference>);
     method public void registerTransferCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.TransferCallback);
     method public void setOnGetControllerHintsListener(@Nullable android.media.MediaRouter2.OnGetControllerHintsListener);
     method public void setRouteListingPreference(@Nullable android.media.RouteListingPreference);
@@ -23990,7 +23999,7 @@
     method public void transferTo(@NonNull android.media.MediaRoute2Info);
     method public void unregisterControllerCallback(@NonNull android.media.MediaRouter2.ControllerCallback);
     method public void unregisterRouteCallback(@NonNull android.media.MediaRouter2.RouteCallback);
-    method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public void unregisterRouteListingPreferenceCallback(@NonNull android.media.MediaRouter2.RouteListingPreferenceCallback);
+    method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public void unregisterRouteListingPreferenceUpdatedCallback(@NonNull java.util.function.Consumer<android.media.RouteListingPreference>);
     method public void unregisterTransferCallback(@NonNull android.media.MediaRouter2.TransferCallback);
   }
 
@@ -24011,11 +24020,6 @@
     method public void onRoutesUpdated(@NonNull java.util.List<android.media.MediaRoute2Info>);
   }
 
-  @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public abstract static class MediaRouter2.RouteListingPreferenceCallback {
-    ctor @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public MediaRouter2.RouteListingPreferenceCallback();
-    method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") public void onRouteListingPreferenceChanged(@Nullable android.media.RouteListingPreference);
-  }
-
   public class MediaRouter2.RoutingController {
     method public void deselectRoute(@NonNull android.media.MediaRoute2Info);
     method @Nullable public android.os.Bundle getControlHints();
@@ -45479,7 +45483,6 @@
     field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED = 2; // 0x2
     field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT = 9; // 0x9
     field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED = 6; // 0x6
-    field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED = 16; // 0x10
     field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
     field public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3; // 0x3
     field public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4; // 0x4
@@ -46718,6 +46721,7 @@
     method @NonNull public android.text.DynamicLayout.Builder setJustificationMode(int);
     method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public android.text.DynamicLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
     method @NonNull public android.text.DynamicLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.DynamicLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
     method @NonNull public android.text.DynamicLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.DynamicLayout.Builder setUseBoundsForWidth(boolean);
     method @NonNull public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean);
@@ -46906,6 +46910,7 @@
     method public int getLineVisibleEnd(int);
     method public float getLineWidth(int);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @IntRange(from=1) public final int getMaxLines();
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics();
     method public int getOffsetForHorizontal(int, float);
     method public int getOffsetToLeftOf(int);
     method public int getOffsetToRightOf(int);
@@ -46972,6 +46977,7 @@
     method @NonNull public android.text.Layout.Builder setLineSpacingAmount(float);
     method @NonNull public android.text.Layout.Builder setLineSpacingMultiplier(@FloatRange(from=0) float);
     method @NonNull public android.text.Layout.Builder setMaxLines(@IntRange(from=1) int);
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.Layout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
     method @NonNull public android.text.Layout.Builder setRightIndents(@Nullable int[]);
     method @NonNull public android.text.Layout.Builder setTextDirectionHeuristic(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.Layout.Builder setUseBoundsForWidth(boolean);
@@ -47243,6 +47249,7 @@
     method @NonNull public android.text.StaticLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
     method @NonNull public android.text.StaticLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
     method @NonNull public android.text.StaticLayout.Builder setMaxLines(@IntRange(from=0) int);
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.StaticLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
     method public android.text.StaticLayout.Builder setText(CharSequence);
     method @NonNull public android.text.StaticLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
     method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.StaticLayout.Builder setUseBoundsForWidth(boolean);
@@ -49852,6 +49859,7 @@
     method public android.view.Display.Mode getMode();
     method public String getName();
     method @Deprecated public int getOrientation();
+    method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") @NonNull public android.hardware.OverlayProperties getOverlaySupport();
     method @Deprecated public int getPixelFormat();
     method @Nullable public android.graphics.ColorSpace getPreferredWideGamutColorSpace();
     method public long getPresentationDeadlineNanos();
@@ -50130,13 +50138,6 @@
     field public static final int VIRTUAL_KEY_RELEASE = 8; // 0x8
   }
 
-  @FlaggedApi("android.view.flags.scroll_feedback_api") public class HapticScrollFeedbackProvider implements android.view.ScrollFeedbackProvider {
-    ctor public HapticScrollFeedbackProvider(@NonNull android.view.View);
-    method public void onScrollLimit(int, int, int, boolean);
-    method public void onScrollProgress(int, int, int, int);
-    method public void onSnapToItem(int, int, int);
-  }
-
   public class InflateException extends java.lang.RuntimeException {
     ctor public InflateException();
     ctor public InflateException(String, Throwable);
@@ -51303,9 +51304,10 @@
   }
 
   @FlaggedApi("android.view.flags.scroll_feedback_api") public interface ScrollFeedbackProvider {
-    method public void onScrollLimit(int, int, int, boolean);
-    method public void onScrollProgress(int, int, int, int);
-    method public void onSnapToItem(int, int, int);
+    method @FlaggedApi("android.view.flags.scroll_feedback_api") @NonNull public static android.view.ScrollFeedbackProvider createProvider(@NonNull android.view.View);
+    method @FlaggedApi("android.view.flags.scroll_feedback_api") public void onScrollLimit(int, int, int, boolean);
+    method @FlaggedApi("android.view.flags.scroll_feedback_api") public void onScrollProgress(int, int, int, int);
+    method @FlaggedApi("android.view.flags.scroll_feedback_api") public void onSnapToItem(int, int, int);
   }
 
   public class SearchEvent {
@@ -52587,7 +52589,6 @@
     method @Deprecated public static int getEdgeSlop();
     method @Deprecated public static int getFadingEdgeLength();
     method @Deprecated public static long getGlobalActionKeyTimeout();
-    method @FlaggedApi("android.view.flags.scroll_feedback_api") public int getHapticScrollFeedbackTickInterval(int, int, int);
     method public static int getJumpTapTimeout();
     method public static int getKeyRepeatDelay();
     method public static int getKeyRepeatTimeout();
@@ -52627,7 +52628,6 @@
     method @Deprecated public static int getWindowTouchSlop();
     method public static long getZoomControlsTimeout();
     method public boolean hasPermanentMenuKey();
-    method @FlaggedApi("android.view.flags.scroll_feedback_api") public boolean isHapticScrollFeedbackEnabled(int, int, int);
     method public boolean shouldShowMenuShortcutsWhenKeyboardPresent();
   }
 
@@ -54520,8 +54520,8 @@
   public class AnimationUtils {
     ctor public AnimationUtils();
     method public static long currentAnimationTimeMillis();
-    method @FlaggedApi("android.view.flags.expected_presentation_time_api") public static long getExpectedPresentationTimeMillis();
-    method @FlaggedApi("android.view.flags.expected_presentation_time_api") public static long getExpectedPresentationTimeNanos();
+    method @FlaggedApi("android.view.flags.expected_presentation_time_read_only") public static long getExpectedPresentationTimeMillis();
+    method @FlaggedApi("android.view.flags.expected_presentation_time_read_only") public static long getExpectedPresentationTimeNanos();
     method public static android.view.animation.Animation loadAnimation(android.content.Context, @AnimRes int) throws android.content.res.Resources.NotFoundException;
     method public static android.view.animation.Interpolator loadInterpolator(android.content.Context, @AnimRes @InterpolatorRes int) throws android.content.res.Resources.NotFoundException;
     method public static android.view.animation.LayoutAnimationController loadLayoutAnimation(android.content.Context, @AnimRes int) throws android.content.res.Resources.NotFoundException;
@@ -59928,6 +59928,7 @@
     method public int getMinHeight();
     method public int getMinLines();
     method public int getMinWidth();
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics();
     method public final android.text.method.MovementMethod getMovementMethod();
     method public int getOffsetForPosition(float, float);
     method public android.text.TextPaint getPaint();
@@ -60064,6 +60065,7 @@
     method public void setMinHeight(int);
     method public void setMinLines(int);
     method public void setMinWidth(int);
+    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
     method public final void setMovementMethod(android.text.method.MovementMethod);
     method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener);
     method public void setPaintFlags(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ac61107..1a7810a 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12744,7 +12744,7 @@
     method @NonNull public android.service.voice.HotwordRejectedResult.Builder setConfidenceLevel(int);
   }
 
-  public final class HotwordTrainingAudio implements android.os.Parcelable {
+  @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public final class HotwordTrainingAudio implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.media.AudioFormat getAudioFormat();
     method @NonNull public int getAudioType();
@@ -12755,7 +12755,7 @@
     field public static final int HOTWORD_OFFSET_UNSET = -1; // 0xffffffff
   }
 
-  public static final class HotwordTrainingAudio.Builder {
+  @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public static final class HotwordTrainingAudio.Builder {
     ctor public HotwordTrainingAudio.Builder(@NonNull byte[], @NonNull android.media.AudioFormat);
     method @NonNull public android.service.voice.HotwordTrainingAudio build();
     method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setAudioFormat(@NonNull android.media.AudioFormat);
@@ -12764,7 +12764,7 @@
     method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordOffsetMillis(int);
   }
 
-  public final class HotwordTrainingData implements android.os.Parcelable {
+  @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public final class HotwordTrainingData implements android.os.Parcelable {
     method public int describeContents();
     method public static int getMaxTrainingDataBytes();
     method public int getTimeoutStage();
@@ -12773,7 +12773,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordTrainingData> CREATOR;
   }
 
-  public static final class HotwordTrainingData.Builder {
+  @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public static final class HotwordTrainingData.Builder {
     ctor public HotwordTrainingData.Builder();
     method @NonNull public android.service.voice.HotwordTrainingData.Builder addTrainingAudio(@NonNull android.service.voice.HotwordTrainingAudio);
     method @NonNull public android.service.voice.HotwordTrainingData build();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 03a58be..779777c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3622,7 +3622,7 @@
 package android.view.animation {
 
   public class AnimationUtils {
-    method @FlaggedApi("android.view.flags.expected_presentation_time_api") public static void lockAnimationClock(long, long);
+    method @FlaggedApi("android.view.flags.expected_presentation_time_read_only") public static void lockAnimationClock(long, long);
     method public static void unlockAnimationClock();
   }
 
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 113a6dd..7320cea 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -51,7 +51,7 @@
 /**
  * Determines when over-the-air system updates are installed on a device. Only a device policy
  * controller (DPC) running in device owner mode or in profile owner mode for an organization-owned
- * device can set an update policy for the device—by calling the {@code DevicePolicyManager} method
+ * device can set an update policy for the device by calling the {@code DevicePolicyManager} method
  * {@link DevicePolicyManager#setSystemUpdatePolicy setSystemUpdatePolicy()}. An update
  * policy affects the pending system update (if there is one) and any future updates for the device.
  *
diff --git a/core/java/android/app/admin/flags/FlagUtils.java b/core/java/android/app/admin/flags/FlagUtils.java
deleted file mode 100644
index 7c3c3d5..0000000
--- a/core/java/android/app/admin/flags/FlagUtils.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.admin.flags;
-
-import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
-import static android.app.admin.flags.Flags.policyEngineMigrationV2Enabled;
-import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
-
-import android.os.Binder;
-
-/**
- *
- * @hide
- */
-public final class FlagUtils {
-    private FlagUtils() {}
-
-    public static boolean isPolicyEngineMigrationV2Enabled() {
-        return Binder.withCleanCallingIdentity(() -> {
-            return policyEngineMigrationV2Enabled();
-        });
-    }
-
-    public static boolean isDevicePolicySizeTrackingEnabled() {
-        return Binder.withCleanCallingIdentity(() -> {
-            return devicePolicySizeTrackingEnabled();
-        });
-    }
-
-    public static boolean isOnboardingBugreportV2Enabled() {
-        return Binder.withCleanCallingIdentity(() -> {
-            return onboardingBugreportV2Enabled();
-        });
-    }
-}
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index f99615f..5a41c65 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -27,3 +27,17 @@
   description: "Allow holders of INTERACT_ACROSS_USERS_FULL to suspend apps in different users."
   bug: "263464464"
 }
+
+flag {
+  name: "dedicated_device_control_enabled"
+  namespace: "enterprise"
+  description: "Allow the device management role holder to control which platform features are available on dedicated devices."
+  bug: "281964214"
+}
+
+flag {
+  name: "security_log_v2_enabled"
+  namespace: "enterprise"
+  description: "Improve access to security logging in the context of Zero Trust."
+  bug: "295324350"
+}
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
index cf54c2a..5f8de77 100644
--- a/core/java/android/app/contentsuggestions/OWNERS
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -1,7 +1,4 @@
 # Bug component: 643919
 
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
+hackz@google.com
+volnov@google.com
diff --git a/core/java/android/app/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
index b34f678..06bff5d 100644
--- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java
+++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
@@ -58,6 +58,11 @@
         super(in);
     }
 
+    @Override
+    boolean isActivityLifecycleItem() {
+        return true;
+    }
+
     /** A final lifecycle state that an activity should reach. */
     @LifecycleState
     public abstract int getTargetState();
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 8617386..9c0cd39 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -45,6 +45,13 @@
  */
 public class ClientTransaction implements Parcelable, ObjectPoolItem {
 
+    /**
+     * List of transaction items that should be executed in order. Including both
+     * {@link ActivityLifecycleItem} and other {@link ClientTransactionItem}.
+     */
+    @Nullable
+    private List<ClientTransactionItem> mTransactionItems;
+
     /** A list of individual callbacks to a client. */
     @UnsupportedAppUsage
     private List<ClientTransactionItem> mActivityCallbacks;
@@ -64,9 +71,32 @@
     }
 
     /**
-     * Add a message to the end of the sequence of callbacks.
-     * @param activityCallback A single message that can contain a lifecycle request/callback.
+     * Adds a message to the end of the sequence of transaction items.
+     * @param item A single message that can contain a client activity/window request/callback.
+     * TODO(b/260873529): replace both {@link #addCallback} and {@link #setLifecycleStateRequest}.
      */
+    public void addTransactionItem(@NonNull ClientTransactionItem item) {
+        if (mTransactionItems == null) {
+            mTransactionItems = new ArrayList<>();
+        }
+        mTransactionItems.add(item);
+    }
+
+    /**
+     * Gets the list of client window requests/callbacks.
+     * TODO(b/260873529): must be non null after remove the deprecated methods.
+     */
+    @Nullable
+    public List<ClientTransactionItem> getTransactionItems() {
+        return mTransactionItems;
+    }
+
+    /**
+     * Adds a message to the end of the sequence of callbacks.
+     * @param activityCallback A single message that can contain a lifecycle request/callback.
+     * @deprecated use {@link #addTransactionItem(ClientTransactionItem)} instead.
+     */
+    @Deprecated
     public void addCallback(@NonNull ClientTransactionItem activityCallback) {
         if (mActivityCallbacks == null) {
             mActivityCallbacks = new ArrayList<>();
@@ -74,25 +104,35 @@
         mActivityCallbacks.add(activityCallback);
     }
 
-    /** Get the list of callbacks. */
+    /**
+     * Gets the list of callbacks.
+     * @deprecated use {@link #getTransactionItems()} instead.
+     */
     @Nullable
     @VisibleForTesting
     @UnsupportedAppUsage
+    @Deprecated
     public List<ClientTransactionItem> getCallbacks() {
         return mActivityCallbacks;
     }
 
-    /** Get the target state lifecycle request. */
+    /**
+     * Gets the target state lifecycle request.
+     * @deprecated use {@link #getTransactionItems()} instead.
+     */
     @VisibleForTesting(visibility = PACKAGE)
     @UnsupportedAppUsage
+    @Deprecated
     public ActivityLifecycleItem getLifecycleStateRequest() {
         return mLifecycleStateRequest;
     }
 
     /**
-     * Set the lifecycle state in which the client should be after executing the transaction.
+     * Sets the lifecycle state in which the client should be after executing the transaction.
      * @param stateRequest A lifecycle request initialized with right parameters.
+     * @deprecated use {@link #addTransactionItem(ClientTransactionItem)} instead.
      */
+    @Deprecated
     public void setLifecycleStateRequest(@NonNull ActivityLifecycleItem stateRequest) {
         mLifecycleStateRequest = stateRequest;
     }
@@ -103,6 +143,14 @@
      *                                 requested by transaction items.
      */
     public void preExecute(@NonNull ClientTransactionHandler clientTransactionHandler) {
+        if (mTransactionItems != null) {
+            final int size = mTransactionItems.size();
+            for (int i = 0; i < size; ++i) {
+                mTransactionItems.get(i).preExecute(clientTransactionHandler);
+            }
+            return;
+        }
+
         if (mActivityCallbacks != null) {
             final int size = mActivityCallbacks.size();
             for (int i = 0; i < size; ++i) {
@@ -147,6 +195,13 @@
 
     @Override
     public void recycle() {
+        if (mTransactionItems != null) {
+            int size = mTransactionItems.size();
+            for (int i = 0; i < size; i++) {
+                mTransactionItems.get(i).recycle();
+            }
+            mTransactionItems = null;
+        }
         if (mActivityCallbacks != null) {
             int size = mActivityCallbacks.size();
             for (int i = 0; i < size; i++) {
@@ -165,8 +220,15 @@
     // Parcelable implementation
 
     /** Write to Parcel. */
+    @SuppressWarnings("AndroidFrameworkEfficientParcelable") // Item class is not final.
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
+        final boolean writeTransactionItems = mTransactionItems != null;
+        dest.writeBoolean(writeTransactionItems);
+        if (writeTransactionItems) {
+            dest.writeParcelableList(mTransactionItems, flags);
+        }
+
         dest.writeParcelable(mLifecycleStateRequest, flags);
         final boolean writeActivityCallbacks = mActivityCallbacks != null;
         dest.writeBoolean(writeActivityCallbacks);
@@ -177,11 +239,20 @@
 
     /** Read from Parcel. */
     private ClientTransaction(@NonNull Parcel in) {
-        mLifecycleStateRequest = in.readParcelable(getClass().getClassLoader(), android.app.servertransaction.ActivityLifecycleItem.class);
+        final boolean readTransactionItems = in.readBoolean();
+        if (readTransactionItems) {
+            mTransactionItems = new ArrayList<>();
+            in.readParcelableList(mTransactionItems, getClass().getClassLoader(),
+                    ClientTransactionItem.class);
+        }
+
+        mLifecycleStateRequest = in.readParcelable(getClass().getClassLoader(),
+                ActivityLifecycleItem.class);
         final boolean readActivityCallbacks = in.readBoolean();
         if (readActivityCallbacks) {
             mActivityCallbacks = new ArrayList<>();
-            in.readParcelableList(mActivityCallbacks, getClass().getClassLoader(), android.app.servertransaction.ClientTransactionItem.class);
+            in.readParcelableList(mActivityCallbacks, getClass().getClassLoader(),
+                    ClientTransactionItem.class);
         }
     }
 
@@ -209,7 +280,8 @@
             return false;
         }
         final ClientTransaction other = (ClientTransaction) o;
-        return Objects.equals(mActivityCallbacks, other.mActivityCallbacks)
+        return Objects.equals(mTransactionItems, other.mTransactionItems)
+                && Objects.equals(mActivityCallbacks, other.mActivityCallbacks)
                 && Objects.equals(mLifecycleStateRequest, other.mLifecycleStateRequest)
                 && mClient == other.mClient;
     }
@@ -217,6 +289,7 @@
     @Override
     public int hashCode() {
         int result = 17;
+        result = 31 * result + Objects.hashCode(mTransactionItems);
         result = 31 * result + Objects.hashCode(mActivityCallbacks);
         result = 31 * result + Objects.hashCode(mLifecycleStateRequest);
         result = 31 * result + Objects.hashCode(mClient);
@@ -227,6 +300,22 @@
     void dump(@NonNull String prefix, @NonNull PrintWriter pw,
             @NonNull ClientTransactionHandler transactionHandler) {
         pw.append(prefix).println("ClientTransaction{");
+        if (mTransactionItems != null) {
+            pw.append(prefix).print("  transactionItems=[");
+            final String itemPrefix = prefix + "    ";
+            final int size = mTransactionItems.size();
+            if (size > 0) {
+                pw.println();
+                for (int i = 0; i < size; i++) {
+                    mTransactionItems.get(i).dump(itemPrefix, pw, transactionHandler);
+                }
+                pw.append(prefix).println("  ]");
+            } else {
+                pw.println("]");
+            }
+            pw.append(prefix).println("}");
+            return;
+        }
         pw.append(prefix).print("  callbacks=[");
         final String itemPrefix = prefix + "    ";
         final int size = mActivityCallbacks != null ? mActivityCallbacks.size() : 0;
diff --git a/core/java/android/app/servertransaction/ClientTransactionItem.java b/core/java/android/app/servertransaction/ClientTransactionItem.java
index 07e5a7d..f94e22d 100644
--- a/core/java/android/app/servertransaction/ClientTransactionItem.java
+++ b/core/java/android/app/servertransaction/ClientTransactionItem.java
@@ -72,6 +72,13 @@
         return null;
     }
 
+    /**
+     * Whether this is a {@link ActivityLifecycleItem}.
+     */
+    boolean isActivityLifecycleItem() {
+        return false;
+    }
+
     /** Dumps this transaction item. */
     void dump(@NonNull String prefix, @NonNull PrintWriter pw,
             @NonNull ClientTransactionHandler transactionHandler) {
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 066f9fe..9f5e0dc 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -28,6 +28,7 @@
 import static android.app.servertransaction.TransactionExecutorHelper.getShortActivityName;
 import static android.app.servertransaction.TransactionExecutorHelper.getStateName;
 import static android.app.servertransaction.TransactionExecutorHelper.lastCallbackRequestingState;
+import static android.app.servertransaction.TransactionExecutorHelper.shouldExcludeLastLifecycleState;
 import static android.app.servertransaction.TransactionExecutorHelper.tId;
 import static android.app.servertransaction.TransactionExecutorHelper.transactionToString;
 
@@ -61,6 +62,9 @@
     private final PendingTransactionActions mPendingActions = new PendingTransactionActions();
     private final TransactionExecutorHelper mHelper = new TransactionExecutorHelper();
 
+    /** Keeps track of display ids whose Configuration got updated within a transaction. */
+    private final ArraySet<Integer> mConfigUpdatedDisplayIds = new ArraySet<>();
+
     /** Initialize an instance with transaction handler, that will execute all requested actions. */
     public TransactionExecutor(@NonNull ClientTransactionHandler clientTransactionHandler) {
         mTransactionHandler = clientTransactionHandler;
@@ -79,15 +83,52 @@
             Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
         }
 
-        executeCallbacks(transaction);
-        executeLifecycleState(transaction);
+        if (transaction.getTransactionItems() != null) {
+            executeTransactionItems(transaction);
+        } else {
+            // TODO(b/260873529): cleanup after launch.
+            executeCallbacks(transaction);
+            executeLifecycleState(transaction);
+        }
+
+        if (!mConfigUpdatedDisplayIds.isEmpty()) {
+            // Whether this transaction should trigger DisplayListener#onDisplayChanged.
+            final ClientTransactionListenerController controller =
+                    ClientTransactionListenerController.getInstance();
+            final int displayCount = mConfigUpdatedDisplayIds.size();
+            for (int i = 0; i < displayCount; i++) {
+                final int displayId = mConfigUpdatedDisplayIds.valueAt(i);
+                controller.onDisplayChanged(displayId);
+            }
+            mConfigUpdatedDisplayIds.clear();
+        }
 
         mPendingActions.clear();
         if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
     }
 
-    /** Cycle through all states requested by callbacks and execute them at proper times. */
+    /** Cycles through all transaction items and execute them at proper times. */
     @VisibleForTesting
+    public void executeTransactionItems(@NonNull ClientTransaction transaction) {
+        final List<ClientTransactionItem> items = transaction.getTransactionItems();
+        final int size = items.size();
+        for (int i = 0; i < size; i++) {
+            final ClientTransactionItem item = items.get(i);
+            if (item.isActivityLifecycleItem()) {
+                executeLifecycleItem(transaction, (ActivityLifecycleItem) item);
+            } else {
+                executeNonLifecycleItem(transaction, item,
+                        shouldExcludeLastLifecycleState(items, i));
+            }
+        }
+    }
+
+    /**
+     * Cycle through all states requested by callbacks and execute them at proper times.
+     * @deprecated use {@link #executeTransactionItems} instead.
+     */
+    @VisibleForTesting
+    @Deprecated
     public void executeCallbacks(@NonNull ClientTransaction transaction) {
         final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
         if (callbacks == null || callbacks.isEmpty()) {
@@ -105,83 +146,78 @@
         // Index of the last callback that requests some post-execution state.
         final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
 
-        // Keep track of display ids whose Configuration got updated with this transaction.
-        ArraySet<Integer> configUpdatedDisplays = null;
-
         final int size = callbacks.size();
         for (int i = 0; i < size; ++i) {
             final ClientTransactionItem item = callbacks.get(i);
-            final IBinder token = item.getActivityToken();
-            ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
 
-            if (token != null && r == null
-                    && mTransactionHandler.getActivitiesToBeDestroyed().containsKey(token)) {
-                // The activity has not been created but has been requested to destroy, so all
-                // transactions for the token are just like being cancelled.
-                Slog.w(TAG, "Skip pre-destroyed transaction item:\n" + item);
-                continue;
-            }
-
-            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
+            // Skip the very last transition and perform it by explicit state request instead.
             final int postExecutionState = item.getPostExecutionState();
-
-            if (item.shouldHaveDefinedPreExecutionState()) {
-                final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
-                        item.getPostExecutionState());
-                if (closestPreExecutionState != UNDEFINED) {
-                    cycleToPath(r, closestPreExecutionState, transaction);
-                }
-            }
-
-            // Can't read flag from isolated process.
-            final boolean isSyncWindowConfigUpdateFlagEnabled = !Process.isIsolated()
-                    && syncWindowConfigUpdateFlag();
-            final Context configUpdatedContext = isSyncWindowConfigUpdateFlagEnabled
-                    ? item.getContextToUpdate(mTransactionHandler)
-                    : null;
-            final Configuration preExecutedConfig = configUpdatedContext != null
-                    ? new Configuration(configUpdatedContext.getResources().getConfiguration())
-                    : null;
-
-            item.execute(mTransactionHandler, mPendingActions);
-
-            if (configUpdatedContext != null) {
-                final Configuration postExecutedConfig = configUpdatedContext.getResources()
-                        .getConfiguration();
-                if (!areConfigurationsEqualForDisplay(postExecutedConfig, preExecutedConfig)) {
-                    if (configUpdatedDisplays == null) {
-                        configUpdatedDisplays = new ArraySet<>();
-                    }
-                    configUpdatedDisplays.add(configUpdatedContext.getDisplayId());
-                }
-            }
-
-            item.postExecute(mTransactionHandler, mPendingActions);
-            if (r == null) {
-                // Launch activity request will create an activity record.
-                r = mTransactionHandler.getActivityClient(token);
-            }
-
-            if (postExecutionState != UNDEFINED && r != null) {
-                // Skip the very last transition and perform it by explicit state request instead.
-                final boolean shouldExcludeLastTransition =
-                        i == lastCallbackRequestingState && finalState == postExecutionState;
-                cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
-            }
-        }
-
-        if (configUpdatedDisplays != null) {
-            final ClientTransactionListenerController controller =
-                    ClientTransactionListenerController.getInstance();
-            final int displayCount = configUpdatedDisplays.size();
-            for (int i = 0; i < displayCount; i++) {
-                final int displayId = configUpdatedDisplays.valueAt(i);
-                controller.onDisplayChanged(displayId);
-            }
+            final boolean shouldExcludeLastLifecycleState = postExecutionState != UNDEFINED
+                    && i == lastCallbackRequestingState && finalState == postExecutionState;
+            executeNonLifecycleItem(transaction, item, shouldExcludeLastLifecycleState);
         }
     }
 
-    /** Transition to the final state if requested by the transaction. */
+    private void executeNonLifecycleItem(@NonNull ClientTransaction transaction,
+            @NonNull ClientTransactionItem item, boolean shouldExcludeLastLifecycleState) {
+        final IBinder token = item.getActivityToken();
+        ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
+
+        if (token != null && r == null
+                && mTransactionHandler.getActivitiesToBeDestroyed().containsKey(token)) {
+            // The activity has not been created but has been requested to destroy, so all
+            // transactions for the token are just like being cancelled.
+            Slog.w(TAG, "Skip pre-destroyed transaction item:\n" + item);
+            return;
+        }
+
+        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
+        final int postExecutionState = item.getPostExecutionState();
+
+        if (item.shouldHaveDefinedPreExecutionState()) {
+            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
+                    postExecutionState);
+            if (closestPreExecutionState != UNDEFINED) {
+                cycleToPath(r, closestPreExecutionState, transaction);
+            }
+        }
+
+        // Can't read flag from isolated process.
+        final boolean isSyncWindowConfigUpdateFlagEnabled = !Process.isIsolated()
+                && syncWindowConfigUpdateFlag();
+        final Context configUpdatedContext = isSyncWindowConfigUpdateFlagEnabled
+                ? item.getContextToUpdate(mTransactionHandler)
+                : null;
+        final Configuration preExecutedConfig = configUpdatedContext != null
+                ? new Configuration(configUpdatedContext.getResources().getConfiguration())
+                : null;
+
+        item.execute(mTransactionHandler, mPendingActions);
+
+        if (configUpdatedContext != null) {
+            final Configuration postExecutedConfig = configUpdatedContext.getResources()
+                    .getConfiguration();
+            if (!areConfigurationsEqualForDisplay(postExecutedConfig, preExecutedConfig)) {
+                mConfigUpdatedDisplayIds.add(configUpdatedContext.getDisplayId());
+            }
+        }
+
+        item.postExecute(mTransactionHandler, mPendingActions);
+        if (r == null) {
+            // Launch activity request will create an activity record.
+            r = mTransactionHandler.getActivityClient(token);
+        }
+
+        if (postExecutionState != UNDEFINED && r != null) {
+            cycleToPath(r, postExecutionState, shouldExcludeLastLifecycleState, transaction);
+        }
+    }
+
+    /**
+     * Transition to the final state if requested by the transaction.
+     * @deprecated use {@link #executeTransactionItems} instead
+     */
+    @Deprecated
     private void executeLifecycleState(@NonNull ClientTransaction transaction) {
         final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
         if (lifecycleItem == null) {
@@ -189,6 +225,11 @@
             return;
         }
 
+        executeLifecycleItem(transaction, lifecycleItem);
+    }
+
+    private void executeLifecycleItem(@NonNull ClientTransaction transaction,
+            @NonNull ActivityLifecycleItem lifecycleItem) {
         final IBinder token = lifecycleItem.getActivityToken();
         final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
         if (DEBUG_RESOLVER) {
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 7e89a5b..dfbccb4 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -236,21 +236,39 @@
      * index 1 will be returned, because ActivityResult request on position 1 will be the last
      * request that moves activity to the RESUMED state where it will eventually end.
      */
-    static int lastCallbackRequestingState(ClientTransaction transaction) {
+    static int lastCallbackRequestingState(@NonNull ClientTransaction transaction) {
         final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
-        if (callbacks == null || callbacks.size() == 0) {
+        if (callbacks == null || callbacks.isEmpty()
+                || transaction.getLifecycleStateRequest() == null) {
             return -1;
         }
+        return lastCallbackRequestingStateIndex(callbacks, 0, callbacks.size() - 1,
+                transaction.getLifecycleStateRequest().getActivityToken());
+    }
 
+    /**
+     * Returns the index of the last callback between the start index and last index that requests
+     * the state for the given activity token in which that activity will be after execution.
+     * If there is a group of callbacks in the end that requests the same specific state or doesn't
+     * request any - we will find the first one from such group.
+     *
+     * E.g. ActivityResult requests RESUMED post-execution state, Configuration does not request any
+     * specific state. If there is a sequence
+     *   Configuration - ActivityResult - Configuration - ActivityResult
+     * index 1 will be returned, because ActivityResult request on position 1 will be the last
+     * request that moves activity to the RESUMED state where it will eventually end.
+     */
+    private static int lastCallbackRequestingStateIndex(@NonNull List<ClientTransactionItem> items,
+            int startIndex, int lastIndex, @NonNull IBinder activityToken) {
         // Go from the back of the list to front, look for the request closes to the beginning that
         // requests the state in which activity will end after all callbacks are executed.
         int lastRequestedState = UNDEFINED;
         int lastRequestingCallback = -1;
-        for (int i = callbacks.size() - 1; i >= 0; i--) {
-            final ClientTransactionItem callback = callbacks.get(i);
-            final int postExecutionState = callback.getPostExecutionState();
-            if (postExecutionState != UNDEFINED) {
-                // Found a callback that requests some post-execution state.
+        for (int i = lastIndex; i >= startIndex; i--) {
+            final ClientTransactionItem item = items.get(i);
+            final int postExecutionState = item.getPostExecutionState();
+            if (postExecutionState != UNDEFINED && activityToken.equals(item.getActivityToken())) {
+                // Found a callback that requests some post-execution state for the given activity.
                 if (lastRequestedState == UNDEFINED || lastRequestedState == postExecutionState) {
                     // It's either a first-from-end callback that requests state or it requests
                     // the same state as the last one. In both cases, we will use it as the new
@@ -266,6 +284,53 @@
         return lastRequestingCallback;
     }
 
+    /**
+     * For the transaction item at {@code currentIndex}, if it is requesting post execution state,
+     * whether or not to exclude the last state. This only returns {@code true} when there is a
+     * following explicit {@link ActivityLifecycleItem} requesting the same state for the same
+     * activity, so that last state will be covered by the following {@link ActivityLifecycleItem}.
+     */
+    static boolean shouldExcludeLastLifecycleState(@NonNull List<ClientTransactionItem> items,
+            int currentIndex) {
+        final ClientTransactionItem item = items.get(currentIndex);
+        final IBinder activityToken = item.getActivityToken();
+        final int postExecutionState = item.getPostExecutionState();
+        if (activityToken == null || postExecutionState == UNDEFINED) {
+            // Not a transaction item requesting post execution state.
+            return false;
+        }
+        final int nextLifecycleItemIndex = findNextLifecycleItemIndex(items, currentIndex + 1,
+                activityToken);
+        if (nextLifecycleItemIndex == -1) {
+            // No following ActivityLifecycleItem for this activity token.
+            return false;
+        }
+        final ActivityLifecycleItem lifecycleItem =
+                (ActivityLifecycleItem) items.get(nextLifecycleItemIndex);
+        if (postExecutionState != lifecycleItem.getTargetState()) {
+            // The explicit ActivityLifecycleItem is not requesting the same state.
+            return false;
+        }
+        // Only exclude for the first non-lifecycle item that requests the same specific state.
+        return currentIndex == lastCallbackRequestingStateIndex(items, currentIndex,
+                nextLifecycleItemIndex - 1, activityToken);
+    }
+
+    /**
+     * Finds the index of the next {@link ActivityLifecycleItem} for the given activity token.
+     */
+    private static int findNextLifecycleItemIndex(@NonNull List<ClientTransactionItem> items,
+            int startIndex, @NonNull IBinder activityToken) {
+        final int size = items.size();
+        for (int i = startIndex; i < size; i++) {
+            final ClientTransactionItem item = items.get(i);
+            if (item.isActivityLifecycleItem() && item.getActivityToken().equals(activityToken)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     /** Dump transaction to string. */
     static String transactionToString(@NonNull ClientTransaction transaction,
             @NonNull ClientTransactionHandler transactionHandler) {
diff --git a/core/java/android/app/usage/flags.aconfig b/core/java/android/app/usage/flags.aconfig
index f401a76..4f1c65b 100644
--- a/core/java/android/app/usage/flags.aconfig
+++ b/core/java/android/app/usage/flags.aconfig
@@ -13,3 +13,11 @@
     description: "Feature flag for the new REPORT_USAGE_STATS permission."
     bug: "296056771"
 }
+
+flag {
+    name: "use_dedicated_handler_thread"
+    namespace: "backstage_power"
+    description: "Flag to use a dedicated thread for usage event process"
+    is_fixed_read_only: true
+    bug: "299336442"
+}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 563ed7d..e9f419e 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.LocusId;
+import android.content.pm.LauncherUserInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.LauncherActivityInfoInternal;
@@ -62,6 +63,7 @@
             in Bundle opts, in UserHandle user);
     PendingIntent getActivityLaunchIntent(String callingPackage, in ComponentName component,
             in UserHandle user);
+    LauncherUserInfo getLauncherUserInfo(in UserHandle user);
     void showAppDetailsAsUser(in IApplicationThread caller, String callingPackage,
             String callingFeatureId, in ComponentName component, in Rect sourceBounds,
             in Bundle opts, in UserHandle user);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index dbaa4c9..0cd4358 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -55,6 +56,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Flags;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -776,6 +778,28 @@
     }
 
     /**
+     * Returns information related to a user which is useful for displaying UI elements
+     * to distinguish it from other users (eg, badges). Only system launchers should
+     * call this API.
+     *
+     * @param userHandle user handle of the user for which LauncherUserInfo is requested
+     * @return the LauncherUserInfo object related to the user specified.
+     * @hide
+     */
+    @Nullable
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public final LauncherUserInfo getLauncherUserInfo(@NonNull UserHandle userHandle) {
+        if (DEBUG) {
+            Log.i(TAG, "getLauncherUserInfo " + userHandle);
+        }
+        try {
+            return mService.getLauncherUserInfo(userHandle);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
      * returns null.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt b/core/java/android/content/pm/LauncherUserInfo.aidl
similarity index 75%
copy from packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
copy to core/java/android/content/pm/LauncherUserInfo.aidl
index 0aa6b0b..f875f1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
+++ b/core/java/android/content/pm/LauncherUserInfo.aidl
@@ -11,12 +11,9 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package com.android.systemui.qs.tiles.base.interactor
+package android.content.pm;
 
-data class QSTileDataRequest(
-    val userId: Int,
-    val trigger: StateUpdateTrigger,
-)
+parcelable LauncherUserInfo;
diff --git a/core/java/android/content/pm/LauncherUserInfo.java b/core/java/android/content/pm/LauncherUserInfo.java
new file mode 100644
index 0000000..214c3e4
--- /dev/null
+++ b/core/java/android/content/pm/LauncherUserInfo.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+/**
+ * The LauncherUserInfo object holds information about an Android user that is required to display
+ * the Launcher related UI elements specific to the user (like badges).
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+public final class LauncherUserInfo implements Parcelable {
+
+    private final String mUserType;
+
+    // Serial number for the user, should be same as in the {@link UserInfo} object.
+    private final int mUserSerialNumber;
+
+    /**
+     * Returns type of the user as defined in {@link UserManager}. e.g.,
+     * {@link UserManager.USER_TYPE_PROFILE_MANAGED} or {@link UserManager.USER_TYPE_PROFILE_ClONE}
+     * TODO(b/303812736): Make the return type public and update javadoc here once the linked bug
+     * is resolved.
+     *
+     * @return the userType for the user whose LauncherUserInfo this is
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    @NonNull
+    public String getUserType() {
+        return mUserType;
+    }
+
+    /**
+     * Returns serial number of user as returned by
+     * {@link UserManager#getSerialNumberForUser(UserHandle)}
+     *
+     * @return the serial number associated with the user
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public int getUserSerialNumber() {
+        return mUserSerialNumber;
+    }
+
+    private LauncherUserInfo(@NonNull Parcel in) {
+        mUserType = in.readString16NoHelper();
+        mUserSerialNumber = in.readInt();
+    }
+
+    @Override
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString16NoHelper(mUserType);
+        dest.writeInt(mUserSerialNumber);
+    }
+
+    @Override
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public int describeContents() {
+        return 0;
+    }
+
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public static final @android.annotation.NonNull Creator<LauncherUserInfo> CREATOR =
+            new Creator<LauncherUserInfo>() {
+                @Override
+                public LauncherUserInfo createFromParcel(Parcel in) {
+                    return new LauncherUserInfo(in);
+                }
+
+                @Override
+                public LauncherUserInfo[] newArray(int size) {
+                    return new LauncherUserInfo[size];
+                }
+            };
+
+    /**
+     * @hide
+     */
+    public static final class Builder {
+        private final String mUserType;
+
+        private final int mUserSerialNumber;
+
+        public Builder(@NonNull String userType, int userSerialNumber) {
+            this.mUserType = userType;
+            this.mUserSerialNumber = userSerialNumber;
+        }
+
+        /**
+         * Builds the LauncherUserInfo object
+         */
+        @NonNull public LauncherUserInfo build() {
+            return new LauncherUserInfo(this.mUserType, this.mUserSerialNumber);
+        }
+
+    } // End builder
+
+    private LauncherUserInfo(@NonNull  String userType, int userSerialNumber) {
+        this.mUserType = userType;
+        this.mUserSerialNumber = userSerialNumber;
+    }
+}
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index db12728..96609ad 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -15,9 +15,9 @@
 }
 
 flag {
-    name: "prevent_sdk_lib_app"
+    name: "disallow_sdk_libs_to_be_apps"
     namespace: "package_manager_service"
-    description: "Feature flag to enable the prevent sdk-library be an application."
+    description: "Feature flag to disallow a <sdk-library> to be an <application>."
     bug: "295843617"
     is_fixed_read_only: true
 }
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index 20771af..524afe9 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -153,7 +153,7 @@
                     mService.getCandidateCredentials(
                             request,
                             new GetCandidateCredentialsTransport(executor, callback),
-                            mContext.getOpPackageName());
+                            callingPackage);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/hardware/OverlayProperties.java b/core/java/android/hardware/OverlayProperties.java
index 8bfc2f7..014cf6d 100644
--- a/core/java/android/hardware/OverlayProperties.java
+++ b/core/java/android/hardware/OverlayProperties.java
@@ -16,21 +16,28 @@
 
 package android.hardware;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
+import android.hardware.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import libcore.util.NativeAllocationRegistry;
 
 /**
- * The class provides overlay properties of the device. OverlayProperties
- * exposes some capabilities from HWC e.g. if fp16 can be supported for HWUI.
+ * Provides supported overlay properties of the device.
  *
- * In the future, more capabilities can be added, e.g., whether or not
- * per-layer colorspaces are supported.
- *
- * @hide
+ * <p>
+ * Hardware overlay is a technique to composite different buffers directly
+ * to the screen using display hardware rather than the GPU.
+ * The system compositor is able to assign any content managed by a
+ * {@link android.view.SurfaceControl} onto a hardware overlay if possible.
+ * Applications may be interested in the display hardware capabilities exposed
+ * by this class as a hint to determine if their {@link android.view.SurfaceControl}
+ * tree is power-efficient and performant.
+ * </p>
  */
+@FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
 public final class OverlayProperties implements Parcelable {
 
     private static final NativeAllocationRegistry sRegistry =
@@ -38,10 +45,12 @@
             nGetDestructor());
 
     private long mNativeObject;
+    // only for virtual displays
+    private static OverlayProperties sDefaultOverlayProperties;
     // Invoked on destruction
     private Runnable mCloser;
 
-    public OverlayProperties(long nativeObject) {
+    private OverlayProperties(long nativeObject) {
         if (nativeObject != 0) {
             mCloser = sRegistry.registerNativeAllocation(this, nativeObject);
         }
@@ -49,7 +58,20 @@
     }
 
     /**
+     * For virtual displays, we provide an overlay properties object
+     * with RGBA 8888 only, sRGB only, true for mixed color spaces.
+     * @hide
+     */
+    public static OverlayProperties getDefault() {
+        if (sDefaultOverlayProperties == null) {
+            sDefaultOverlayProperties = new OverlayProperties(nCreateDefault());
+        }
+        return sDefaultOverlayProperties;
+    }
+
+    /**
      * @return True if the device can support fp16, false otherwise.
+     * @hide
      */
     public boolean supportFp16ForHdr() {
         if (mNativeObject == 0) {
@@ -59,8 +81,13 @@
     }
 
     /**
-     * @return True if the device can support mixed colorspaces, false otherwise.
+     * Indicates that hw composition of two or more overlays
+     * with different colorspaces is supported on the device.
+     *
+     * @return True if the device can support mixed colorspaces efficiently,
+     *         false if GPU composition fallback is otherwise required.
      */
+    @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
     public boolean supportMixedColorSpaces() {
         if (mNativeObject == 0) {
             return false;
@@ -68,28 +95,14 @@
         return nSupportMixedColorSpaces(mNativeObject);
     }
 
-    /**
-     * Release the local reference.
-     */
-    public void release() {
-        if (mNativeObject != 0) {
-            mCloser.run();
-            mNativeObject = 0;
-        }
-    }
 
+    @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
     @Override
     public int describeContents() {
         return 0;
     }
 
-    /**
-     * Flatten this object in to a Parcel.
-     *
-     * @param dest The Parcel in which the object should be written.
-     * @param flags Additional flags about how the object should be written.
-     *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
-     */
+    @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         if (mNativeObject == 0) {
@@ -100,6 +113,7 @@
         nWriteOverlayPropertiesToParcel(mNativeObject, dest);
     }
 
+    @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API)
     public static final @NonNull Parcelable.Creator<OverlayProperties> CREATOR =
             new Parcelable.Creator<OverlayProperties>() {
         public OverlayProperties createFromParcel(Parcel in) {
@@ -115,6 +129,7 @@
     };
 
     private static native long nGetDestructor();
+    private static native long nCreateDefault();
     private static native boolean nSupportFp16ForHdr(long nativeObject);
     private static native boolean nSupportMixedColorSpaces(long nativeObject);
     private static native void nWriteOverlayPropertiesToParcel(long nativeObject, Parcel dest);
diff --git a/core/java/android/hardware/flags/overlayproperties_flags.aconfig b/core/java/android/hardware/flags/overlayproperties_flags.aconfig
new file mode 100644
index 0000000..c6a352e
--- /dev/null
+++ b/core/java/android/hardware/flags/overlayproperties_flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.hardware.flags"
+
+flag {
+    name: "overlayproperties_class_api"
+    namespace: "core_graphics"
+    description: "public OverlayProperties class, OverlayProperties#supportMixedColorSpaces and Display#getOverlaySupport API"
+    bug: "267234573"
+}
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
index 861e440..6952e5d 100644
--- a/core/java/android/hardware/hdmi/OWNERS
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -2,5 +2,4 @@
 
 include /services/core/java/com/android/server/display/OWNERS
 
-marvinramin@google.com
-lcnathalie@google.com
+quxiangfang@google.com
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 4c2bbc1..ba80811 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -3363,6 +3363,13 @@
                 return true;
             }
             return false;
+        } else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && KeyEvent.metaStateHasModifiers(
+                event.getMetaState() & ~KeyEvent.META_SHIFT_MASK, KeyEvent.META_CTRL_ON)) {
+            if (mDecorViewVisible && mWindowVisible) {
+                int direction = (event.getMetaState() & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
+                mPrivOps.switchKeyboardLayoutAsync(direction);
+                return true;
+            }
         }
         return doMovementKey(keyCode, event, MOVEMENT_DOWN);
     }
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 958669e..ae3e333 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -34,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
+import java.util.regex.Pattern;
 
 /**********************************************************************
  * This file is not a part of the NFC mainline module                 *
@@ -79,7 +80,7 @@
             throw new IllegalArgumentException("Too many AIDs in AID group.");
         }
         for (String aid : aids) {
-            if (!CardEmulation.isValidAid(aid)) {
+            if (!isValidAid(aid)) {
                 throw new IllegalArgumentException("AID " + aid + " is not a valid AID.");
             }
         }
@@ -264,4 +265,34 @@
         return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
                 CardEmulation.CATEGORY_OTHER.equals(category);
     }
+
+    private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
+    /**
+     * Copied over from {@link CardEmulation#isValidAid(String)}
+     * @hide
+     */
+    private static boolean isValidAid(String aid) {
+        if (aid == null)
+            return false;
+
+        // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
+        if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        // If not a prefix/subset AID, the total length must be even (even # of AID chars)
+        if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        // Verify hex characters
+        if (!AID_PATTERN.matcher(aid).matches()) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 18ec914..665b753 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -52,6 +52,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 /**
  * Class holding APDU service info.
@@ -307,7 +308,7 @@
                             com.android.internal.R.styleable.AidFilter);
                     String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
                             toUpperCase();
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                    if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
                         currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -321,7 +322,7 @@
                             toUpperCase();
                     // Add wildcard char to indicate prefix
                     aid = aid.concat("*");
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                    if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
                         currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -335,7 +336,7 @@
                             toUpperCase();
                     // Add wildcard char to indicate suffix
                     aid = aid.concat("#");
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                    if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
                         currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -806,7 +807,7 @@
      */
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public void dumpDebug(@NonNull ProtoOutputStream proto) {
-        Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
+        getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
         proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
         if (!mOnHost) {
@@ -825,4 +826,34 @@
         }
         proto.write(ApduServiceInfoProto.SETTINGS_ACTIVITY_NAME, mSettingsActivityName);
     }
+
+    private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
+    /**
+     * Copied over from {@link CardEmulation#isValidAid(String)}
+     * @hide
+     */
+    private static boolean isValidAid(String aid) {
+        if (aid == null)
+            return false;
+
+        // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
+        if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        // If not a prefix/subset AID, the total length must be even (even # of AID chars)
+        if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        // Verify hex characters
+        if (!AID_PATTERN.matcher(aid).matches()) {
+            Log.e(TAG, "AID " + aid + " is not a valid AID.");
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index ec919e4..33bc169 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -173,7 +173,7 @@
                             com.android.internal.R.styleable.SystemCodeFilter);
                     systemCode = a.getString(
                             com.android.internal.R.styleable.SystemCodeFilter_name).toUpperCase();
-                    if (!NfcFCardEmulation.isValidSystemCode(systemCode) &&
+                    if (!isValidSystemCode(systemCode) &&
                             !systemCode.equalsIgnoreCase("NULL")) {
                         Log.e(TAG, "Invalid System Code: " + systemCode);
                         systemCode = null;
@@ -187,7 +187,7 @@
                             com.android.internal.R.styleable.Nfcid2Filter_name).toUpperCase();
                     if (!nfcid2.equalsIgnoreCase("RANDOM") &&
                             !nfcid2.equalsIgnoreCase("NULL") &&
-                            !NfcFCardEmulation.isValidNfcid2(nfcid2)) {
+                            !isValidNfcid2(nfcid2)) {
                         Log.e(TAG, "Invalid NFCID2: " + nfcid2);
                         nfcid2 = null;
                     }
@@ -436,10 +436,62 @@
      */
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public void dumpDebug(@NonNull ProtoOutputStream proto) {
-        Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
+        getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
         proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
         proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
         proto.write(NfcFServiceInfoProto.T3T_PMM, getT3tPmm());
     }
+
+    /**
+     * Copied over from {@link NfcFCardEmulation#isValidSystemCode(String)}
+     * @hide
+     */
+    private static boolean isValidSystemCode(String systemCode) {
+        if (systemCode == null) {
+            return false;
+        }
+        if (systemCode.length() != 4) {
+            Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+            return false;
+        }
+        // check if the value is between "4000" and "4FFF" (excluding "4*FF")
+        if (!systemCode.startsWith("4") || systemCode.toUpperCase().endsWith("FF")) {
+            Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+            return false;
+        }
+        try {
+            Integer.parseInt(systemCode, 16);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Copied over from {@link NfcFCardEmulation#isValidNfcid2(String)}
+     * @hide
+     */
+    private static boolean isValidNfcid2(String nfcid2) {
+        if (nfcid2 == null) {
+            return false;
+        }
+        if (nfcid2.length() != 16) {
+            Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+            return false;
+        }
+        // check if the the value starts with "02FE"
+        if (!nfcid2.toUpperCase().startsWith("02FE")) {
+            Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+            return false;
+        }
+        try {
+            Long.parseLong(nfcid2, 16);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/core/java/android/os/OomKillRecord.java b/core/java/android/os/OomKillRecord.java
index 151a65f..ca1d49a 100644
--- a/core/java/android/os/OomKillRecord.java
+++ b/core/java/android/os/OomKillRecord.java
@@ -15,10 +15,15 @@
  */
 package android.os;
 
+import com.android.internal.util.FrameworkStatsLog;
 
 /**
+ * Activity manager communication with kernel out-of-memory (OOM) data handling
+ * and statsd atom logging.
+ *
  * Expected data to get back from the OOM event's file.
- * Note that this should be equivalent to the struct <b>OomKill</b> inside
+ * Note that this class fields' should be equivalent to the struct
+ * <b>OomKill</b> inside
  * <pre>
  * system/memory/libmeminfo/libmemevents/include/memevents.h
  * </pre>
@@ -41,6 +46,18 @@
         this.mOomScoreAdj = oomScoreAdj;
     }
 
+    /**
+     * Logs the event when the kernel OOM killer claims a victims to reduce
+     * memory pressure.
+     * KernelOomKillOccurred = 754
+     */
+    public void logKillOccurred() {
+        FrameworkStatsLog.write(
+                FrameworkStatsLog.KERNEL_OOM_KILL_OCCURRED,
+                mUid, mPid, mOomScoreAdj, mTimeStampInMillis,
+                mProcessName);
+    }
+
     public long getTimestampMilli() {
         return mTimeStampInMillis;
     }
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 800149c..94eca3d 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -12,6 +12,7 @@
     namespace: "hardware_backed_security"
     description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys"
     bug: "296464083"
+    is_fixed_read_only: true
 }
 
 flag {
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index a29bf7a..1afe8d9 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -1401,6 +1401,7 @@
         parcel.writeParcelable(mAuthentication, flags);
         parcel.writeString(mId);
         parcel.writeInt(mEligibleReason);
+        parcel.writeTypedObject(mAuthenticationExtras, flags);
     }
 
     public static final @NonNull Creator<Dataset> CREATOR = new Creator<Dataset>() {
@@ -1436,6 +1437,7 @@
                     android.content.IntentSender.class);
             final String datasetId = parcel.readString();
             final int eligibleReason = parcel.readInt();
+            final Bundle authenticationExtras = parcel.readTypedObject(Bundle.CREATOR);
 
             // Always go through the builder to ensure the data ingested by
             // the system obeys the contract of the builder to avoid attacks
@@ -1480,6 +1482,7 @@
                         fieldDialogPresentation);
             }
             builder.setAuthentication(authentication);
+            builder.setAuthenticationExtras(authenticationExtras);
             builder.setId(datasetId);
             Dataset dataset = builder.build();
             dataset.mEligibleReason = eligibleReason;
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.java b/core/java/android/service/voice/HotwordTrainingAudio.java
index 91e34dc..916fa36b 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.java
+++ b/core/java/android/service/voice/HotwordTrainingAudio.java
@@ -16,6 +16,7 @@
 
 package android.service.voice;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -23,6 +24,7 @@
 import android.media.AudioFormat;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.service.voice.flags.Flags;
 
 import com.android.internal.util.DataClass;
 
@@ -33,6 +35,7 @@
  *
  * @hide
  */
+@FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
 @DataClass(
         genConstructor = false,
         genBuilder = true,
@@ -65,12 +68,12 @@
 
     /**
      * App-defined identifier to distinguish hotword training audio instances.
-     */
+     * <p> Returns -1 if unset. */
     @NonNull
     private final int mAudioType;
 
     private static int defaultAudioType() {
-        return 0;
+        return -1;
     }
 
     /**
@@ -152,6 +155,7 @@
 
     /**
      * App-defined identifier to distinguish hotword training audio instances.
+     * <p> Returns -1 if unset.
      */
     @DataClass.Generated.Member
     public @NonNull int getAudioType() {
@@ -274,6 +278,7 @@
     /**
      * A builder for {@link HotwordTrainingAudio}
      */
+    @FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
     @SuppressWarnings("WeakerAccess")
     @DataClass.Generated.Member
     public static final class Builder extends BaseBuilder {
@@ -318,6 +323,7 @@
 
         /**
          * App-defined identifier to distinguish hotword training audio instances.
+         * <p> Returns -1 if unset.
          */
         @DataClass.Generated.Member
         public @NonNull Builder setAudioType(@NonNull int value) {
@@ -368,7 +374,7 @@
     }
 
     @DataClass.Generated(
-            time = 1694193905346L,
+            time = 1697827049629L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordTrainingAudio.java",
             inputSignatures = "public static final  int HOTWORD_OFFSET_UNSET\nprivate final @android.annotation.NonNull byte[] mHotwordAudio\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull int mAudioType\nprivate  int mHotwordOffsetMillis\nprivate  java.lang.String hotwordAudioToString()\nprivate static  int defaultAudioType()\nclass HotwordTrainingAudio extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\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.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/service/voice/HotwordTrainingData.java b/core/java/android/service/voice/HotwordTrainingData.java
index 31aeb9c..aa6dab3 100644
--- a/core/java/android/service/voice/HotwordTrainingData.java
+++ b/core/java/android/service/voice/HotwordTrainingData.java
@@ -16,10 +16,12 @@
 
 package android.service.voice;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.service.voice.flags.Flags;
 import android.text.TextUtils;
 
 import com.android.internal.util.DataClass;
@@ -47,6 +49,7 @@
         genParcelable = true,
         genToString = true)
 @SystemApi
+@FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
 public final class HotwordTrainingData implements Parcelable {
     /** Max size for hotword training data in bytes. */
     public static int getMaxTrainingDataBytes() {
@@ -63,11 +66,11 @@
     }
 
     /** App-defined stage when hotword model timed-out while running.
-     * <p> Returns 0 if unset. */
+     * <p> Returns -1 if unset. */
     private final int mTimeoutStage;
 
     private static int defaultTimeoutStage() {
-        return 0;
+        return -1;
     }
 
     private void onConstructed() {
@@ -120,7 +123,7 @@
 
     /**
      * App-defined stage when hotword model timed-out while running.
-     * <p> Returns 0 if unset.
+     * <p> Returns -1 if unset.
      */
     @DataClass.Generated.Member
     public int getTimeoutStage() {
@@ -218,6 +221,7 @@
     /**
      * A builder for {@link HotwordTrainingData}
      */
+    @FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
     @SuppressWarnings("WeakerAccess")
     @DataClass.Generated.Member
     public static final class Builder {
@@ -251,7 +255,7 @@
 
         /**
          * App-defined stage when hotword model timed-out while running.
-         * <p> Returns 0 if unset.
+         * <p> Returns -1 if unset.
          */
         @DataClass.Generated.Member
         public @NonNull Builder setTimeoutStage(int value) {
@@ -287,7 +291,7 @@
     }
 
     @DataClass.Generated(
-            time = 1696092128091L,
+            time = 1697826948280L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordTrainingData.java",
             inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"trainingAudio\") java.util.List<android.service.voice.HotwordTrainingAudio> mTrainingAudioList\nprivate final  int mTimeoutStage\npublic static  int getMaxTrainingDataBytes()\nprivate static  java.util.List<android.service.voice.HotwordTrainingAudio> defaultTrainingAudioList()\nprivate static  int defaultTimeoutStage()\nprivate  void onConstructed()\nclass HotwordTrainingData 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)")
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 65a1da6..4c81888 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -190,7 +190,8 @@
             @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth,
             boolean useFallbackLineSpacing) {
         return replaceOrMake(source, paint, outerWidth, align, 1.0f, 0.0f, metrics, includePad,
-                ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */);
+                ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */,
+                null /* minimumFontMetrics */);
     }
 
     /** @hide */
@@ -199,7 +200,8 @@
             @NonNull Alignment align, float spacingMultiplier, float spacingAmount,
             @NonNull BoringLayout.Metrics metrics, boolean includePad,
             @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth,
-            boolean useFallbackLineSpacing, boolean useBoundsForWidth) {
+            boolean useFallbackLineSpacing, boolean useBoundsForWidth,
+            @Nullable Paint.FontMetrics minimumFontMetrics) {
         boolean trust;
 
         if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
@@ -270,7 +272,8 @@
                 spacingAdd, includePad, false /* fallbackLineSpacing */,
                 outerwidth /* ellipsizedWidth */, null /* ellipsize */, 1 /* maxLines */,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
-                null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false);
+                null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false,
+                null);
 
         mEllipsizedWidth = outerwidth;
         mEllipsizedStart = 0;
@@ -343,7 +346,7 @@
                 ellipsizedWidth, ellipsize, 1 /* maxLines */,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
                 null /* rightIndents */, JUSTIFICATION_MODE_NONE,
-                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */);
+                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */, null);
     }
 
     /** @hide */
@@ -359,12 +362,13 @@
             int ellipsizedWidth,
             TextUtils.TruncateAt ellipsize,
             Metrics metrics,
-            boolean useBoundsForWidth) {
+            boolean useBoundsForWidth,
+            @Nullable Paint.FontMetrics minimumFontMetrics) {
         this(text, paint, width, align, TextDirectionHeuristics.LTR,
                 spacingMult, spacingAdd, includePad, fallbackLineSpacing, ellipsizedWidth,
                 ellipsize, 1 /* maxLines */, Layout.BREAK_STRATEGY_SIMPLE,
                 Layout.HYPHENATION_FREQUENCY_NONE, null, null, Layout.JUSTIFICATION_MODE_NONE,
-                LineBreakConfig.NONE, metrics, useBoundsForWidth);
+                LineBreakConfig.NONE, metrics, useBoundsForWidth, minimumFontMetrics);
     }
 
     /* package */ BoringLayout(
@@ -387,12 +391,13 @@
             int justificationMode,
             LineBreakConfig lineBreakConfig,
             Metrics metrics,
-            boolean useBoundsForWidth) {
+            boolean useBoundsForWidth,
+            @Nullable Paint.FontMetrics minimumFontMetrics) {
 
         super(text, paint, width, align, textDir, spacingMult, spacingAdd, includePad,
                 fallbackLineSpacing, ellipsizedWidth, ellipsize, maxLines, breakStrategy,
                 hyphenationFrequency, leftIndents, rightIndents, justificationMode,
-                lineBreakConfig, useBoundsForWidth);
+                lineBreakConfig, useBoundsForWidth, minimumFontMetrics);
 
 
         boolean trust;
@@ -548,6 +553,15 @@
     public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint,
             @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing,
             @Nullable Metrics metrics) {
+        return isBoring(text, paint, textDir, useFallbackLineSpacing, null, metrics);
+    }
+
+    /**
+     * @hide
+     */
+    public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint,
+            @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing,
+            @Nullable Paint.FontMetrics minimumFontMetrics, @Nullable Metrics metrics) {
         final int textLength = text.length();
         if (hasAnyInterestingChars(text, textLength)) {
            return null;  // There are some interesting characters. Not boring.
@@ -570,6 +584,19 @@
             fm.reset();
         }
 
+        if (ClientFlags.fixLineHeightForLocale()) {
+            if (minimumFontMetrics == null) {
+                paint.getFontMetricsIntForLocale(fm);
+            } else {
+                fm.set(minimumFontMetrics);
+                // Because the font metrics is provided by public APIs, adjust the top/bottom with
+                // ascent/descent: top must be smaller than ascent, bottom must be larger than
+                // descent.
+                fm.top = Math.min(fm.top, fm.ascent);
+                fm.bottom = Math.max(fm.bottom, fm.descent);
+            }
+        }
+
         TextLine line = TextLine.obtain();
         line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
                 Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
diff --git a/core/java/android/text/ClientFlags.java b/core/java/android/text/ClientFlags.java
index 46fa501..0421d5a 100644
--- a/core/java/android/text/ClientFlags.java
+++ b/core/java/android/text/ClientFlags.java
@@ -27,14 +27,6 @@
  * @hide
  */
 public class ClientFlags {
-
-    /**
-     * @see Flags#deprecateFontsXml()
-     */
-    public static boolean deprecateFontsXml() {
-        return TextFlags.isFeatureEnabled(Flags.FLAG_DEPRECATE_FONTS_XML);
-    }
-
     /**
      * @see Flags#noBreakNoHyphenationSpan()
      */
@@ -55,4 +47,11 @@
     public static boolean useBoundsForWidth() {
         return TextFlags.isFeatureEnabled(Flags.FLAG_USE_BOUNDS_FOR_WIDTH);
     }
+
+    /**
+     * @see Flags#fixLineHeightForLocale()
+     */
+    public static boolean fixLineHeightForLocale() {
+        return TextFlags.isFeatureEnabled(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE);
+    }
 }
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index a0cd074..7b9cb6a 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
 import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN;
 import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
 
@@ -315,6 +316,43 @@
         }
 
         /**
+         * Set the minimum font metrics used for line spacing.
+         *
+         * <p>
+         * {@code null} is the default value. If {@code null} is set or left as default, the
+         * font metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} is
+         * used.
+         *
+         * <p>
+         * The minimum meaning here is the minimum value of line spacing: maximum value of
+         * {@link Paint#ascent()}, minimum value of {@link Paint#descent()}.
+         *
+         * <p>
+         * By setting this value, each line will have minimum line spacing regardless of the text
+         * rendered. For example, usually Japanese script has larger vertical metrics than Latin
+         * script. By setting the metrics obtained by
+         * {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} for Japanese or leave it
+         * {@code null} if the Paint's locale is Japanese, the line spacing for Japanese is reserved
+         * if the text is an English text. If the vertical metrics of the text is larger than
+         * Japanese, for example Burmese, the bigger font metrics is used.
+         *
+         * @param minimumFontMetrics A minimum font metrics. Passing {@code null} for using the
+         *                          value obtained by
+         *                          {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+         * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see android.widget.TextView#getMinimumFontMetrics()
+         * @see Layout#getMinimumFontMetrics()
+         * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         */
+        @NonNull
+        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+        public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) {
+            mMinimumFontMetrics = minimumFontMetrics;
+            return this;
+        }
+
+        /**
          * Build the {@link DynamicLayout} after options have been set.
          *
          * <p>Note: the builder object must not be reused in any way after calling this method.
@@ -347,6 +385,7 @@
         private int mEllipsizedWidth;
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
+        private @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
         private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -422,7 +461,7 @@
                 false /* fallbackLineSpacing */, ellipsizedWidth, ellipsize,
                 Integer.MAX_VALUE /* maxLines */, breakStrategy, hyphenationFrequency,
                 null /* leftIndents */, null /* rightIndents */, justificationMode,
-                lineBreakConfig, false /* useBoundsForWidth */);
+                lineBreakConfig, false /* useBoundsForWidth */, null /* minimumFontMetrics */);
 
         final Builder b = Builder.obtain(base, paint, width)
                 .setAlignment(align)
@@ -448,7 +487,7 @@
                 b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                 Integer.MAX_VALUE /* maxLines */, b.mBreakStrategy, b.mHyphenationFrequency,
                 null /* leftIndents */, null /* rightIndents */, b.mJustificationMode,
-                b.mLineBreakConfig, b.mUseBoundsForWidth);
+                b.mLineBreakConfig, b.mUseBoundsForWidth, b.mMinimumFontMetrics);
 
         mDisplay = b.mDisplay;
         mIncludePad = b.mIncludePad;
@@ -476,6 +515,7 @@
         mBase = b.mBase;
         mFallbackLineSpacing = b.mFallbackLineSpacing;
         mUseBoundsForWidth = b.mUseBoundsForWidth;
+        mMinimumFontMetrics = b.mMinimumFontMetrics;
         if (b.mEllipsize != null) {
             mInts = new PackedIntVector(COLUMNS_ELLIPSIZE);
             mEllipsizedWidth = b.mEllipsizedWidth;
@@ -672,6 +712,7 @@
                 .setAddLastLineLineSpacing(!islast)
                 .setIncludePad(false)
                 .setUseBoundsForWidth(mUseBoundsForWidth)
+                .setMinimumFontMetrics(mMinimumFontMetrics)
                 .setCalculateBounds(true);
 
         reflowed = b.buildPartialStaticLayoutForDynamicLayout(true /* trackpadding */, reflowed);
@@ -1324,6 +1365,7 @@
     private Rect mTempRect = new Rect();
 
     private boolean mUseBoundsForWidth;
+    @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
     @UnsupportedAppUsage
     private static StaticLayout sStaticLayout = null;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 4f4dea7..47c29d9 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
 import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
 
 import android.annotation.FlaggedApi;
@@ -287,7 +288,7 @@
         this(text, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingMult, spacingAdd, false, false, 0, null, Integer.MAX_VALUE,
                 BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null, null,
-                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false);
+                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null);
     }
 
     /**
@@ -336,7 +337,8 @@
             int[] rightIndents,
             int justificationMode,
             LineBreakConfig lineBreakConfig,
-            boolean useBoundsForWidth
+            boolean useBoundsForWidth,
+            Paint.FontMetrics minimumFontMetrics
     ) {
 
         if (width < 0)
@@ -371,6 +373,7 @@
         mJustificationMode = justificationMode;
         mLineBreakConfig = lineBreakConfig;
         mUseBoundsForWidth = useBoundsForWidth;
+        mMinimumFontMetrics = minimumFontMetrics;
     }
 
     /**
@@ -3332,6 +3335,7 @@
     private int mJustificationMode;
     private LineBreakConfig mLineBreakConfig;
     private boolean mUseBoundsForWidth;
+    private @Nullable Paint.FontMetrics mMinimumFontMetrics;
 
     /** @hide */
     @IntDef(prefix = { "DIR_" }, value = {
@@ -3787,12 +3791,48 @@
             return this;
         }
 
+        /**
+         * Set the minimum font metrics used for line spacing.
+         *
+         * <p>
+         * {@code null} is the default value. If {@code null} is set or left it as default, the font
+         * metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} is used.
+         *
+         * <p>
+         * The minimum meaning here is the minimum value of line spacing: maximum value of
+         * {@link Paint#ascent()}, minimum value of {@link Paint#descent()}.
+         *
+         * <p>
+         * By setting this value, each line will have minimum line spacing regardless of the text
+         * rendered. For example, usually Japanese script has larger vertical metrics than Latin
+         * script. By setting the metrics obtained by
+         * {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} for Japanese or leave it
+         * {@code null} if the Paint's locale is Japanese, the line spacing for Japanese is reserved
+         * if the text is an English text. If the vertical metrics of the text is larger than
+         * Japanese, for example Burmese, the bigger font metrics is used.
+         *
+         * @param minimumFontMetrics A minimum font metrics. Passing {@code null} for using the
+         *                          value obtained by
+         *                          {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+         * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see android.widget.TextView#getMinimumFontMetrics()
+         * @see Layout#getMinimumFontMetrics()
+         * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         */
+        @NonNull
+        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+        public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) {
+            mMinimumFontMetrics = minimumFontMetrics;
+            return this;
+        }
+
         private BoringLayout.Metrics isBoring() {
             if (mStart != 0 || mEnd != mText.length()) {  // BoringLayout only support entire text.
                 return null;
             }
             BoringLayout.Metrics metrics = BoringLayout.isBoring(mText, mPaint, mTextDir,
-                    mFallbackLineSpacing, null);
+                    mFallbackLineSpacing, mMinimumFontMetrics, null);
             if (metrics == null) {
                 return null;
             }
@@ -3833,7 +3873,8 @@
                         mText, mPaint, mWidth, mAlignment, mTextDir, mSpacingMult, mSpacingAdd,
                         mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines,
                         mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents,
-                        mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth);
+                        mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth,
+                        mMinimumFontMetrics);
             }
         }
 
@@ -3858,6 +3899,7 @@
         private int mJustificationMode = JUSTIFICATION_MODE_NONE;
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
+        private Paint.FontMetrics mMinimumFontMetrics;
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -4164,4 +4206,22 @@
     public boolean getUseBoundsForWidth() {
         return mUseBoundsForWidth;
     }
+
+    /**
+     * Get the minimum font metrics used for line spacing.
+     *
+     * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see android.widget.TextView#getMinimumFontMetrics()
+     * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     *
+     * @return a minimum font metrics. {@code null} for using the value obtained by
+     *         {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+     */
+    @Nullable
+    @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+    public Paint.FontMetrics getMinimumFontMetrics() {
+        return mMinimumFontMetrics;
+    }
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 01279ce..77e616b 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
 import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
 
 import android.annotation.FlaggedApi;
@@ -460,6 +461,43 @@
         }
 
         /**
+         * Set the minimum font metrics used for line spacing.
+         *
+         * <p>
+         * {@code null} is the default value. If {@code null} is set or left as default, the
+         * font metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} is
+         * used.
+         *
+         * <p>
+         * The minimum meaning here is the minimum value of line spacing: maximum value of
+         * {@link Paint#ascent()}, minimum value of {@link Paint#descent()}.
+         *
+         * <p>
+         * By setting this value, each line will have minimum line spacing regardless of the text
+         * rendered. For example, usually Japanese script has larger vertical metrics than Latin
+         * script. By setting the metrics obtained by
+         * {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} for Japanese or leave it
+         * {@code null} if the Paint's locale is Japanese, the line spacing for Japanese is reserved
+         * if the text is an English text. If the vertical metrics of the text is larger than
+         * Japanese, for example Burmese, the bigger font metrics is used.
+         *
+         * @param minimumFontMetrics A minimum font metrics. Passing {@code null} for using the
+         *                          value obtained by
+         *                          {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+         * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see android.widget.TextView#getMinimumFontMetrics()
+         * @see Layout#getMinimumFontMetrics()
+         * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+         */
+        @NonNull
+        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+        public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) {
+            mMinimumFontMetrics = minimumFontMetrics;
+            return this;
+        }
+
+        /**
          * Build the {@link StaticLayout} after options have been set.
          *
          * <p>Note: the builder object must not be reused in any way after calling this
@@ -520,6 +558,7 @@
         private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
         private boolean mUseBoundsForWidth;
         private boolean mCalculateBounds;
+        @Nullable private Paint.FontMetrics mMinimumFontMetrics;
 
         private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -550,7 +589,8 @@
                 null,  // rightIndents
                 JUSTIFICATION_MODE_NONE,
                 null,  // lineBreakConfig,
-                false  // useBoundsForWidth
+                false,  // useBoundsForWidth
+                null  // minimumFontMetrics
         );
 
         mColumns = COLUMNS_ELLIPSIZE;
@@ -627,7 +667,8 @@
                 b.mPaint, b.mWidth, b.mAlignment, b.mTextDir, b.mSpacingMult, b.mSpacingAdd,
                 b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                 b.mMaxLines, b.mBreakStrategy, b.mHyphenationFrequency, b.mLeftIndents,
-                b.mRightIndents, b.mJustificationMode, b.mLineBreakConfig, b.mUseBoundsForWidth);
+                b.mRightIndents, b.mJustificationMode, b.mLineBreakConfig, b.mUseBoundsForWidth,
+                b.mMinimumFontMetrics);
 
         mColumns = columnSize;
         if (b.mEllipsize != null) {
@@ -711,6 +752,35 @@
             indents = null;
         }
 
+        int defaultTop;
+        int defaultAscent;
+        int defaultDescent;
+        int defaultBottom;
+        if (ClientFlags.fixLineHeightForLocale()) {
+            if (b.mMinimumFontMetrics != null) {
+                defaultTop = (int) Math.floor(b.mMinimumFontMetrics.top);
+                defaultAscent = Math.round(b.mMinimumFontMetrics.ascent);
+                defaultDescent = Math.round(b.mMinimumFontMetrics.descent);
+                defaultBottom = (int) Math.ceil(b.mMinimumFontMetrics.bottom);
+            } else {
+                paint.getFontMetricsIntForLocale(fm);
+                defaultTop = fm.top;
+                defaultAscent = fm.ascent;
+                defaultDescent = fm.descent;
+                defaultBottom = fm.bottom;
+            }
+
+            // Because the font metrics is provided by public APIs, adjust the top/bottom with
+            // ascent/descent: top must be smaller than ascent, bottom must be larger than descent.
+            defaultTop = Math.min(defaultTop, defaultAscent);
+            defaultBottom = Math.max(defaultBottom, defaultDescent);
+        } else {
+            defaultTop = 0;
+            defaultAscent = 0;
+            defaultDescent = 0;
+            defaultBottom = 0;
+        }
+
         final LineBreaker lineBreaker = new LineBreaker.Builder()
                 .setBreakStrategy(b.mBreakStrategy)
                 .setHyphenationFrequency(getBaseHyphenationFrequency(b.mHyphenationFrequency))
@@ -889,7 +959,10 @@
             // measuring
             int here = paraStart;
 
-            int fmTop = 0, fmBottom = 0, fmAscent = 0, fmDescent = 0;
+            int fmTop = defaultTop;
+            int fmBottom = defaultBottom;
+            int fmAscent = defaultAscent;
+            int fmDescent = defaultDescent;
             int fmCacheIndex = 0;
             int spanEndCacheIndex = 0;
             int breakIndex = 0;
@@ -982,7 +1055,15 @@
                 && mLineCount < mMaximumVisibleLineCount) {
             final MeasuredParagraph measuredPara =
                     MeasuredParagraph.buildForBidi(source, bufEnd, bufEnd, textDir, null);
-            paint.getFontMetricsInt(fm);
+            if (ClientFlags.fixLineHeightForLocale()) {
+                fm.top = defaultTop;
+                fm.ascent = defaultAscent;
+                fm.descent = defaultDescent;
+                fm.bottom = defaultBottom;
+            } else {
+                paint.getFontMetricsInt(fm);
+            }
+
             v = out(source,
                     bufEnd, bufEnd, fm.ascent, fm.descent,
                     fm.top, fm.bottom,
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
index 9edf298..2466386 100644
--- a/core/java/android/text/TextFlags.java
+++ b/core/java/android/text/TextFlags.java
@@ -55,10 +55,10 @@
      * List of text flags to be transferred to the application process.
      */
     public static final String[] TEXT_ACONFIGS_FLAGS = {
-            Flags.FLAG_DEPRECATE_FONTS_XML,
             Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN,
             Flags.FLAG_PHRASE_STRICT_FALLBACK,
             Flags.FLAG_USE_BOUNDS_FOR_WIDTH,
+            Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE,
     };
 
     /**
@@ -67,10 +67,10 @@
      * The order must be the same to the TEXT_ACONFIG_FLAGS.
      */
     public static final boolean[] TEXT_ACONFIG_DEFAULT_VALUE = {
-            Flags.deprecateFontsXml(),
             Flags.noBreakNoHyphenationSpan(),
             Flags.phraseStrictFallback(),
             Flags.useBoundsForWidth(),
+            Flags.fixLineHeightForLocale(),
     };
 
     /**
diff --git a/core/java/android/text/flags/custom_locale_fallback.aconfig b/core/java/android/text/flags/custom_locale_fallback.aconfig
deleted file mode 100644
index 52fe883..0000000
--- a/core/java/android/text/flags/custom_locale_fallback.aconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "custom_locale_fallback"
-  namespace: "text"
-  description: "A feature flag that adds custom locale fallback to the vendor customization XML. This enables vendors to add their locale specific fonts, e.g. Japanese font."
-  is_fixed_read_only: true
-  bug: "278768958"
-}
diff --git a/core/java/android/text/flags/deprecate_fonts_xml.aconfig b/core/java/android/text/flags/deprecate_fonts_xml.aconfig
deleted file mode 100644
index 5362138..0000000
--- a/core/java/android/text/flags/deprecate_fonts_xml.aconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "deprecate_fonts_xml"
-  namespace: "text"
-  description: "Feature flag for deprecating fonts.xml. By setting true for this feature flag, the new font configuration XML, /system/etc/font_fallback.xml is used. The new XML has a new syntax and flexibility of variable font declarations, but it is not compatible with the apps that reads fonts.xml. So, fonts.xml is maintained as a subset of the font_fallback.xml"
-  # Make read only, as it could be used before the Settings provider is initialized.
-  is_fixed_read_only: true
-  bug: "281769620"
-}
diff --git a/core/java/android/text/flags/fix_double_underline.aconfig b/core/java/android/text/flags/fix_double_underline.aconfig
deleted file mode 100644
index b0aa72a..0000000
--- a/core/java/android/text/flags/fix_double_underline.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "fix_double_underline"
-  namespace: "text"
-  description: "Feature flag for fixing double underline because of the multiple font used in the single line."
-  bug: "297336724"
-}
diff --git a/core/java/android/text/flags/fix_line_height_for_locale.aconfig b/core/java/android/text/flags/fix_line_height_for_locale.aconfig
deleted file mode 100644
index 8696bfa..0000000
--- a/core/java/android/text/flags/fix_line_height_for_locale.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "fix_line_height_for_locale"
-  namespace: "text"
-  description: "Feature flag that preserve the line height of the TextView and EditText even if the the locale is different from Latin"
-  bug: "303326708"
-}
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
new file mode 100644
index 0000000..201f680
--- /dev/null
+++ b/core/java/android/text/flags/flags.aconfig
@@ -0,0 +1,63 @@
+package: "com.android.text.flags"
+
+flag {
+  name: "vendor_custom_locale_fallback"
+  namespace: "text"
+  description: "A feature flag that adds custom locale fallback to the vendor customization XML. This enables vendors to add their locale specific fonts, e.g. Japanese font."
+  is_fixed_read_only: true
+  bug: "278768958"
+}
+
+flag {
+  name: "new_fonts_fallback_xml"
+  namespace: "text"
+  description: "Feature flag for deprecating fonts.xml. By setting true for this feature flag, the new font configuration XML, /system/etc/font_fallback.xml is used. The new XML has a new syntax and flexibility of variable font declarations, but it is not compatible with the apps that reads fonts.xml. So, fonts.xml is maintained as a subset of the font_fallback.xml"
+  # Make read only, as it could be used before the Settings provider is initialized.
+  is_fixed_read_only: true
+  bug: "281769620"
+}
+
+flag {
+  name: "fix_double_underline"
+  namespace: "text"
+  description: "Feature flag for fixing double underline because of the multiple font used in the single line."
+  bug: "297336724"
+}
+
+flag {
+  name: "fix_line_height_for_locale"
+  namespace: "text"
+  description: "Feature flag that preserve the line height of the TextView and EditText even if the the locale is different from Latin"
+  bug: "303326708"
+}
+
+flag {
+  name: "no_break_no_hyphenation_span"
+  namespace: "text"
+  description: "A feature flag that adding new spans that prevents line breaking and hyphenation."
+  bug: "283193586"
+}
+
+flag {
+  name: "use_optimized_boottime_font_loading"
+  namespace: "text"
+  description: "Feature flag ensuring that font is loaded once and asynchronously."
+  # Make read only, as font loading is in the critical boot path which happens before the read-write
+  # flags propagate to the device.
+  is_fixed_read_only: true
+  bug: "304406888"
+}
+
+flag {
+  name: "phrase_strict_fallback"
+  namespace: "text"
+  description: "Feature flag for automatic fallback from phrase based line break to strict line break."
+  bug: "281970875"
+}
+
+flag {
+  name: "use_bounds_for_width"
+  namespace: "text"
+  description: "Feature flag for preventing horizontal clipping."
+  bug: "63938206"
+}
diff --git a/core/java/android/text/flags/no_break_no_hyphenation_span.aconfig b/core/java/android/text/flags/no_break_no_hyphenation_span.aconfig
deleted file mode 100644
index 60f1e88..0000000
--- a/core/java/android/text/flags/no_break_no_hyphenation_span.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "no_break_no_hyphenation_span"
-  namespace: "text"
-  description: "A feature flag that adding new spans that prevents line breaking and hyphenation."
-  bug: "283193586"
-}
diff --git a/core/java/android/text/flags/optimized_font_loading.aconfig b/core/java/android/text/flags/optimized_font_loading.aconfig
deleted file mode 100644
index 0e4a69f..0000000
--- a/core/java/android/text/flags/optimized_font_loading.aconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "use_optimized_boottime_font_loading"
-  namespace: "text"
-  description: "Feature flag ensuring that font is loaded once and asynchronously."
-  # Make read only, as font loading is in the critical boot path which happens before the read-write
-  # flags propagate to the device.
-  is_fixed_read_only: true
-  bug: "304406888"
-}
diff --git a/core/java/android/text/flags/phrase_strict_fallback.aconfig b/core/java/android/text/flags/phrase_strict_fallback.aconfig
deleted file mode 100644
index c67a21b..0000000
--- a/core/java/android/text/flags/phrase_strict_fallback.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "phrase_strict_fallback"
-  namespace: "text"
-  description: "Feature flag for automatic fallback from phrase based line break to strict line break."
-  bug: "281970875"
-}
diff --git a/core/java/android/text/flags/use_bounds_for_width.aconfig b/core/java/android/text/flags/use_bounds_for_width.aconfig
deleted file mode 100644
index d89d5f4..0000000
--- a/core/java/android/text/flags/use_bounds_for_width.aconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-package: "com.android.text.flags"
-
-flag {
-  name: "use_bounds_for_width"
-  namespace: "text"
-  description: "Feature flag for preventing horizontal clipping."
-  bug: "63938206"
-}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 17c7fcc..07dd882 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -18,8 +18,10 @@
 
 import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
 import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
+import static android.hardware.flags.Flags.FLAG_OVERLAYPROPERTIES_CLASS_API;
 
 import android.Manifest;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1468,17 +1470,18 @@
     }
 
     /**
-     * Returns null if it's virtual display.
-     * @hide
+     * Returns the {@link OverlayProperties} of the display.
      */
-    @Nullable
+    @FlaggedApi(FLAG_OVERLAYPROPERTIES_CLASS_API)
+    @NonNull
     public OverlayProperties getOverlaySupport() {
         synchronized (mLock) {
             updateDisplayInfoLocked();
-            if (mDisplayInfo.type != TYPE_VIRTUAL) {
+            if (mDisplayInfo.type == TYPE_INTERNAL
+                    || mDisplayInfo.type == TYPE_EXTERNAL) {
                 return mGlobal.getOverlaySupport();
             }
-            return null;
+            return OverlayProperties.getDefault();
         }
     }
 
@@ -2091,7 +2094,8 @@
         private final int mModeId;
         private final int mWidth;
         private final int mHeight;
-        private final float mRefreshRate;
+        private final float mPeakRefreshRate;
+        private final float mVsyncRate;
         @NonNull
         private final float[] mAlternativeRefreshRates;
         @NonNull
@@ -2103,7 +2107,15 @@
          */
         @TestApi
         public Mode(int width, int height, float refreshRate) {
-            this(INVALID_MODE_ID, width, height, refreshRate, new float[0], new int[0]);
+            this(INVALID_MODE_ID, width, height, refreshRate, refreshRate, new float[0],
+                    new int[0]);
+        }
+
+        /**
+         * @hide
+         */
+        public Mode(int width, int height, float refreshRate, float vsyncRate) {
+            this(INVALID_MODE_ID, width, height, refreshRate, vsyncRate, new float[0], new int[0]);
         }
 
         /**
@@ -2111,18 +2123,29 @@
          */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public Mode(int modeId, int width, int height, float refreshRate) {
-            this(modeId, width, height, refreshRate, new float[0], new int[0]);
+            this(modeId, width, height, refreshRate, refreshRate, new float[0], new int[0]);
         }
 
         /**
          * @hide
          */
         public Mode(int modeId, int width, int height, float refreshRate,
+                    float[] alternativeRefreshRates,
+                    @HdrCapabilities.HdrType int[] supportedHdrTypes) {
+            this(modeId, width, height, refreshRate, refreshRate, alternativeRefreshRates,
+                    supportedHdrTypes);
+        }
+
+        /**
+         * @hide
+         */
+        public Mode(int modeId, int width, int height, float refreshRate, float vsyncRate,
                 float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes) {
             mModeId = modeId;
             mWidth = width;
             mHeight = height;
-            mRefreshRate = refreshRate;
+            mPeakRefreshRate = refreshRate;
+            mVsyncRate = vsyncRate;
             mAlternativeRefreshRates =
                     Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length);
             Arrays.sort(mAlternativeRefreshRates);
@@ -2173,7 +2196,17 @@
          * Returns the refresh rate in frames per second.
          */
         public float getRefreshRate() {
-            return mRefreshRate;
+            return mPeakRefreshRate;
+        }
+
+        /**
+         * Returns the vsync rate in frames per second.
+         * The physical vsync rate may be higher than the refresh rate, as the refresh rate may be
+         * constrained by the system.
+         * @hide
+         */
+        public float getVsyncRate() {
+            return mVsyncRate;
         }
 
         /**
@@ -2219,7 +2252,7 @@
         public boolean matches(int width, int height, float refreshRate) {
             return mWidth == width &&
                     mHeight == height &&
-                    Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate);
+                    Float.floatToIntBits(mPeakRefreshRate) == Float.floatToIntBits(refreshRate);
         }
 
         /**
@@ -2232,9 +2265,9 @@
          *
          * @hide
          */
-        public boolean matchesIfValid(int width, int height, float refreshRate) {
+        public boolean matchesIfValid(int width, int height, float peakRefreshRate) {
             if (!isWidthValid(width) && !isHeightValid(height)
-                    && !isRefreshRateValid(refreshRate)) {
+                    && !isRefreshRateValid(peakRefreshRate)) {
                 return false;
             }
             if (isWidthValid(width) != isHeightValid(height)) {
@@ -2242,8 +2275,9 @@
             }
             return (!isWidthValid(width) || mWidth == width)
                     && (!isHeightValid(height) || mHeight == height)
-                    && (!isRefreshRateValid(refreshRate)
-                    || Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate));
+                    && (!isRefreshRateValid(peakRefreshRate)
+                    || Float.floatToIntBits(mPeakRefreshRate)
+                            == Float.floatToIntBits(peakRefreshRate));
         }
 
         /**
@@ -2262,7 +2296,7 @@
          * @hide
          */
         public boolean isRefreshRateSet() {
-            return mRefreshRate != INVALID_DISPLAY_REFRESH_RATE;
+            return mPeakRefreshRate != INVALID_DISPLAY_REFRESH_RATE;
         }
 
         /**
@@ -2283,7 +2317,8 @@
                 return false;
             }
             Mode that = (Mode) other;
-            return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate)
+            return mModeId == that.mModeId
+                    && matches(that.mWidth, that.mHeight, that.mPeakRefreshRate)
                     && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates)
                     && Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes);
         }
@@ -2294,7 +2329,8 @@
             hash = hash * 17 + mModeId;
             hash = hash * 17 + mWidth;
             hash = hash * 17 + mHeight;
-            hash = hash * 17 + Float.floatToIntBits(mRefreshRate);
+            hash = hash * 17 + Float.floatToIntBits(mPeakRefreshRate);
+            hash = hash * 17 + Float.floatToIntBits(mVsyncRate);
             hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates);
             hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes);
             return hash;
@@ -2306,7 +2342,8 @@
                     .append("id=").append(mModeId)
                     .append(", width=").append(mWidth)
                     .append(", height=").append(mHeight)
-                    .append(", fps=").append(mRefreshRate)
+                    .append(", fps=").append(mPeakRefreshRate)
+                    .append(", vsync=").append(mVsyncRate)
                     .append(", alternativeRefreshRates=")
                     .append(Arrays.toString(mAlternativeRefreshRates))
                     .append(", supportedHdrTypes=")
@@ -2321,8 +2358,8 @@
         }
 
         private Mode(Parcel in) {
-            this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray(),
-                    in.createIntArray());
+            this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.readFloat(),
+                    in.createFloatArray(), in.createIntArray());
         }
 
         @Override
@@ -2330,7 +2367,8 @@
             out.writeInt(mModeId);
             out.writeInt(mWidth);
             out.writeInt(mHeight);
-            out.writeFloat(mRefreshRate);
+            out.writeFloat(mPeakRefreshRate);
+            out.writeFloat(mVsyncRate);
             out.writeFloatArray(mAlternativeRefreshRates);
             out.writeIntArray(mSupportedHdrTypes);
         }
diff --git a/core/java/android/view/HapticScrollFeedbackProvider.java b/core/java/android/view/HapticScrollFeedbackProvider.java
index 1310b0c..6b354a0 100644
--- a/core/java/android/view/HapticScrollFeedbackProvider.java
+++ b/core/java/android/view/HapticScrollFeedbackProvider.java
@@ -16,16 +16,10 @@
 
 package android.view;
 
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.view.flags.Flags;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * {@link ScrollFeedbackProvider} that performs haptic feedback when scrolling.
  *
@@ -36,16 +30,12 @@
  * methods in this class. To check if your input device ID, source, and motion axis are valid for
  * haptic feedback, you can use the
  * {@link ViewConfiguration#isHapticScrollFeedbackEnabled(int, int, int)} API.
+ *
+ * @hide
  */
-@FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
 public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {
     private static final String TAG = "HapticScrollFeedbackProvider";
 
-    /** @hide */
-    @IntDef(value = {MotionEvent.AXIS_SCROLL})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface HapticScrollFeedbackAxis {}
-
     private static final int TICK_INTERVAL_NO_TICK = 0;
     private static final boolean INITIAL_END_OF_LIST_HAPTICS_ENABLED = false;
 
@@ -89,8 +79,7 @@
     }
 
     @Override
-    public void onScrollProgress(
-            int inputDeviceId, int source, @HapticScrollFeedbackAxis int axis, int deltaInPixels) {
+    public void onScrollProgress(int inputDeviceId, int source, int axis, int deltaInPixels) {
         maybeUpdateCurrentConfig(inputDeviceId, source, axis);
         if (!mHapticScrollFeedbackEnabled) {
             return;
@@ -117,8 +106,7 @@
     }
 
     @Override
-    public void onScrollLimit(
-            int inputDeviceId, int source, @HapticScrollFeedbackAxis int axis, boolean isStart) {
+    public void onScrollLimit(int inputDeviceId, int source, int axis, boolean isStart) {
         maybeUpdateCurrentConfig(inputDeviceId, source, axis);
         if (!mHapticScrollFeedbackEnabled) {
             return;
@@ -135,7 +123,7 @@
     }
 
     @Override
-    public void onSnapToItem(int inputDeviceId, int source, @HapticScrollFeedbackAxis int axis) {
+    public void onSnapToItem(int inputDeviceId, int source, int axis) {
         maybeUpdateCurrentConfig(inputDeviceId, source, axis);
         if (!mHapticScrollFeedbackEnabled) {
             return;
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index fb24211..90663c7 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1283,7 +1283,6 @@
             @AnimationType int animationType,
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
             boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) {
-        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
         if ((types & mTypesBeingCancelled) != 0) {
             final boolean monitoredAnimation =
                     animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE;
@@ -1295,12 +1294,15 @@
                     ImeTracker.forLatency().onHideCancelled(statsToken,
                             PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
                 }
+                ImeTracker.forLogging().onCancelled(statsToken,
+                        ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
             }
             throw new IllegalStateException("Cannot start a new insets animation of "
                     + Type.toString(types)
                     + " while an existing " + Type.toString(mTypesBeingCancelled)
                     + " is being cancelled.");
         }
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
         if (types == 0) {
             // nothing to animate.
             listener.onCancelled(null);
@@ -1309,8 +1311,6 @@
             Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
             return;
         }
-        ImeTracker.forLogging().onProgress(statsToken,
-                ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
         if (DEBUG) Log.d(TAG, "controlAnimation types: " + types);
         mLastStartedAnimTypes |= types;
 
diff --git a/core/java/android/view/ScrollFeedbackProvider.java b/core/java/android/view/ScrollFeedbackProvider.java
index 0ba4148..8a44d4f 100644
--- a/core/java/android/view/ScrollFeedbackProvider.java
+++ b/core/java/android/view/ScrollFeedbackProvider.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
 import android.view.flags.Flags;
 
 /**
@@ -62,23 +63,37 @@
  * </ul>
  *
  * <b>Note</b> that not all valid input device source and motion axis inputs are necessarily
- * supported for scroll feedback. If you are implementing this interface, provide clear
- * documentation in your implementation class about which input device source and motion axis are
- * supported for your specific implementation. If you are using one of the implementations of this
- * interface, please refer to the documentation of the implementation for details on which input
- * device source and axis are supported.
+ * supported for scroll feedback; the implementation may choose to provide no feedback for some
+ * valid input device source and motion axis arguments.
  */
 @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
 public interface ScrollFeedbackProvider {
+
+    /**
+     * Creates a {@link ScrollFeedbackProvider} implementation for this device.
+     *
+     * <p>Use a feedback provider created by this method, unless you intend to use your custom
+     * scroll feedback providing logic. This allows your use cases to generate scroll feedback that
+     * is consistent with the rest of the use cases on the device.
+     *
+     * @param view the {@link View} for which to provide scroll feedback.
+     * @return the default {@link ScrollFeedbackProvider} implementation for the device.
+     */
+    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
+    @NonNull
+    static ScrollFeedbackProvider createProvider(@NonNull View view) {
+        return new HapticScrollFeedbackProvider(view);
+    }
+
     /**
      * Call this when the view has snapped to an item.
      *
-     *
      * @param inputDeviceId the ID of the {@link InputDevice} that generated the motion triggering
      *          the snap.
      * @param source the input source of the motion causing the snap.
      * @param axis the axis of {@code event} that caused the item to snap.
      */
+    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
     void onSnapToItem(int inputDeviceId, int source, int axis);
 
     /**
@@ -99,6 +114,7 @@
      *                "start" for some views may be at the bottom of a scrolling list, while it may
      *                be at the top of scrolling list for others.
      */
+    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
     void onScrollLimit(int inputDeviceId, int source, int axis, boolean isStart);
 
     /**
@@ -122,5 +138,6 @@
      * @param axis the axis of {@code event} that caused scroll progress.
      * @param deltaInPixels the amount of scroll progress, in pixels.
      */
+    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
     void onScrollProgress(int inputDeviceId, int source, int axis, int deltaInPixels);
 }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 42a0c9a..e22207c 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1796,7 +1796,7 @@
         public float yDpi;
 
         // Some modes have peak refresh rate lower than the panel vsync rate.
-        public float refreshRate;
+        public float peakRefreshRate;
         // Fixed rate of vsync deadlines for the panel.
         // This can be higher then the peak refresh rate for some panel technologies
         // See: VrrConfig.aidl
@@ -1820,7 +1820,7 @@
                     + ", height=" + height
                     + ", xDpi=" + xDpi
                     + ", yDpi=" + yDpi
-                    + ", refreshRate=" + refreshRate
+                    + ", peakRefreshRate=" + peakRefreshRate
                     + ", vsyncRate=" + vsyncRate
                     + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos
                     + ", presentationDeadlineNanos=" + presentationDeadlineNanos
@@ -1838,7 +1838,7 @@
                     && height == that.height
                     && Float.compare(that.xDpi, xDpi) == 0
                     && Float.compare(that.yDpi, yDpi) == 0
-                    && Float.compare(that.refreshRate, refreshRate) == 0
+                    && Float.compare(that.peakRefreshRate, peakRefreshRate) == 0
                     && Float.compare(that.vsyncRate, vsyncRate) == 0
                     && appVsyncOffsetNanos == that.appVsyncOffsetNanos
                     && presentationDeadlineNanos == that.presentationDeadlineNanos
@@ -1848,7 +1848,7 @@
 
         @Override
         public int hashCode() {
-            return Objects.hash(id, width, height, xDpi, yDpi, refreshRate, vsyncRate,
+            return Objects.hash(id, width, height, xDpi, yDpi, peakRefreshRate, vsyncRate,
                     appVsyncOffsetNanos, presentationDeadlineNanos, group,
                     Arrays.hashCode(supportedHdrTypes));
         }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 2cf5d5d..ec96167 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import android.annotation.FlaggedApi;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
@@ -1272,12 +1271,10 @@
      * @see InputDevice#getMotionRanges()
      * @see InputDevice#getMotionRange(int)
      * @see InputDevice#getMotionRange(int, int)
+     *
+     * @hide
      */
-    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
-    public boolean isHapticScrollFeedbackEnabled(
-            int inputDeviceId,
-            @HapticScrollFeedbackProvider.HapticScrollFeedbackAxis int axis,
-            int source) {
+    public boolean isHapticScrollFeedbackEnabled(int inputDeviceId, int axis, int source) {
         if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return false;
 
         if (source == InputDevice.SOURCE_ROTARY_ENCODER && axis == MotionEvent.AXIS_SCROLL) {
@@ -1318,12 +1315,10 @@
      *      returns {@code Integer.MAX_VALUE}.
      *
      * @see #isHapticScrollFeedbackEnabled(int, int, int)
+     *
+     * @hide
      */
-    @FlaggedApi(Flags.FLAG_SCROLL_FEEDBACK_API)
-    public int getHapticScrollFeedbackTickInterval(
-            int inputDeviceId,
-            @HapticScrollFeedbackProvider.HapticScrollFeedbackAxis int axis,
-            int source) {
+    public int getHapticScrollFeedbackTickInterval(int inputDeviceId, int axis, int source) {
         if (!mRotaryEncoderHapticScrollFeedbackEnabled) {
             return NO_HAPTIC_SCROLL_TICK_INTERVAL;
         }
@@ -1343,9 +1338,6 @@
      * Checks if the View-based haptic scroll feedback implementation is enabled for
      * {@link InputDevice#SOURCE_ROTARY_ENCODER}s.
      *
-     * <p>If this method returns {@code true}, the {@link HapticScrollFeedbackProvider} will be
-     * muted for rotary encoders in favor of View's scroll haptics implementation.
-     *
      * @hide
      */
     public boolean isViewBasedRotaryEncoderHapticScrollFeedbackEnabled() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4a10cab..dfada58 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4751,7 +4751,7 @@
         mFullRedrawNeeded = false;
 
         mIsDrawing = true;
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, mTag + "-draw");
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw-" + mTag);
 
         addFrameCommitCallbackIfNeeded();
 
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 32256b9..b3359b7 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -16,8 +16,8 @@
 
 package android.view.animation;
 
-import static android.view.flags.Flags.FLAG_EXPECTED_PRESENTATION_TIME_API;
-import static android.view.flags.Flags.expectedPresentationTimeApi;
+import static android.view.flags.Flags.FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY;
+import static android.view.flags.Flags.expectedPresentationTimeReadOnly;
 
 import android.annotation.AnimRes;
 import android.annotation.FlaggedApi;
@@ -67,6 +67,11 @@
     @Overridable
     public static final long OVERRIDE_ENABLE_EXPECTED_PRSENTATION_TIME = 278730197L;
 
+    private static boolean sExpectedPresentationTimeFlagValue;
+    static {
+        sExpectedPresentationTimeFlagValue = expectedPresentationTimeReadOnly();
+    }
+
     private static class AnimationState {
         boolean animationClockLocked;
         long currentVsyncTimeMillis;
@@ -108,12 +113,12 @@
      * @hide
      */
     @TestApi
-    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_API)
+    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY)
     public static void lockAnimationClock(long vsyncMillis, long expectedPresentationTimeNanos) {
         AnimationState state = sAnimationState.get();
         state.animationClockLocked = true;
         state.currentVsyncTimeMillis = vsyncMillis;
-        if (!expectedPresentationTimeApi()) {
+        if (!sExpectedPresentationTimeFlagValue) {
             state.mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
         }
     }
@@ -158,9 +163,9 @@
      * @return the expected presentation time of a frame in the
      *         {@link System#nanoTime()} time base.
      */
-    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_API)
+    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY)
     public static long getExpectedPresentationTimeNanos() {
-        if (!expectedPresentationTimeApi()) {
+        if (!sExpectedPresentationTimeFlagValue) {
             return SystemClock.uptimeMillis();
         }
 
@@ -176,7 +181,7 @@
      * @return the expected presentation time of a frame in the
      *         {@link SystemClock#uptimeMillis()} time base.
      */
-    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_API)
+    @FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY)
     public static long getExpectedPresentationTimeMillis() {
         return getExpectedPresentationTimeNanos() / TimeUtils.NANOS_PER_MS;
     }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a40ff64..96574f5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -3392,7 +3392,7 @@
             return false;
         }
         for (String hint : hints) {
-            if (Objects.equals(hint, View.AUTOFILL_HINT_CREDENTIAL_MANAGER)) {
+            if (hint != null && hint.startsWith(View.AUTOFILL_HINT_CREDENTIAL_MANAGER)) {
                 return true;
             }
         }
diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig
index fd96890..2b08eeb 100644
--- a/core/java/android/view/flags/refresh_rate_flags.aconfig
+++ b/core/java/android/view/flags/refresh_rate_flags.aconfig
@@ -22,6 +22,14 @@
 }
 
 flag {
+    name: "expected_presentation_time_read_only"
+    namespace: "toolkit"
+    description: "Feature flag for using expected presentation time of the Choreographer"
+    bug: "278730197"
+    is_fixed_read_only: true
+}
+
+flag {
   name: "set_frame_rate_callback"
   namespace: "core_graphics"
   description: "Enable the `setFrameRate` callback"
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index f9d8b08..1bc7353 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -172,7 +172,6 @@
             PHASE_CLIENT_HANDLE_HIDE_INSETS,
             PHASE_CLIENT_APPLY_ANIMATION,
             PHASE_CLIENT_CONTROL_ANIMATION,
-            PHASE_CLIENT_DISABLED_USER_ANIMATION,
             PHASE_CLIENT_COLLECT_SOURCE_CONTROLS,
             PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW,
             PHASE_CLIENT_REQUEST_IME_SHOW,
@@ -292,9 +291,6 @@
     /** Started the IME window insets show animation. */
     int PHASE_CLIENT_CONTROL_ANIMATION = ImeProtoEnums.PHASE_CLIENT_CONTROL_ANIMATION;
 
-    /** Checked that the IME is controllable. */
-    int PHASE_CLIENT_DISABLED_USER_ANIMATION = ImeProtoEnums.PHASE_CLIENT_DISABLED_USER_ANIMATION;
-
     /** Collecting insets source controls. */
     int PHASE_CLIENT_COLLECT_SOURCE_CONTROLS = ImeProtoEnums.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS;
 
diff --git a/core/java/android/view/inputmethod/TextAppearanceInfo.java b/core/java/android/view/inputmethod/TextAppearanceInfo.java
index 7eee33f..9f0b31b 100644
--- a/core/java/android/view/inputmethod/TextAppearanceInfo.java
+++ b/core/java/android/view/inputmethod/TextAppearanceInfo.java
@@ -770,7 +770,7 @@
         }
 
         /**
-         * Set the font variation settings. Returns null if no variation is specified.
+         * Set the font variation settings. Set {@code null} if no variation is specified.
          *
          * @see Paint#getFontVariationSettings()
          */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a0628c4..6da6a64 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -28,6 +28,7 @@
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
 import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
 
+import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
 import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
 
 import android.R;
@@ -865,6 +866,7 @@
     private final boolean mUseTextPaddingForUiTranslation;
 
     private boolean mUseBoundsForWidth;
+    @Nullable private Paint.FontMetrics mMinimumFontMetrics;
 
     @ViewDebug.ExportedProperty(category = "text")
     @UnsupportedAppUsage
@@ -4901,6 +4903,58 @@
     }
 
     /**
+     * Set the minimum font metrics used for line spacing.
+     *
+     * <p>
+     * {@code null} is the default value. If {@code null} is set or left as default, the font
+     * metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} is used.
+     *
+     * <p>
+     * The minimum meaning here is the minimum value of line spacing: maximum value of
+     * {@link Paint#ascent()}, minimum value of {@link Paint#descent()}.
+     *
+     * <p>
+     * By setting this value, each line will have minimum line spacing regardless of the text
+     * rendered. For example, usually Japanese script has larger vertical metrics than Latin script.
+     * By setting the metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+     * for Japanese or leave it {@code null} if the TextView's locale or system locale is Japanese,
+     * the line spacing for Japanese is reserved if the TextView contains English text. If the
+     * vertical metrics of the text is larger than Japanese, for example Burmese, the bigger font
+     * metrics is used.
+     *
+     * @param minimumFontMetrics A minimum font metrics. Passing {@code null} for using the value
+     *                           obtained by
+     *                           {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+     * @see #getMinimumFontMetrics()
+     * @see Layout#getMinimumFontMetrics()
+     * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     */
+    @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+    public void setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) {
+        mMinimumFontMetrics = minimumFontMetrics;
+    }
+
+    /**
+     * Get the minimum font metrics used for line spacing.
+     *
+     * @see #setMinimumFontMetrics(Paint.FontMetrics)
+     * @see Layout#getMinimumFontMetrics()
+     * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
+     *
+     * @return a minimum font metrics. {@code null} for using the value obtained by
+     *         {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
+     */
+    @Nullable
+    @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+    public Paint.FontMetrics getMinimumFontMetrics() {
+        return mMinimumFontMetrics;
+    }
+
+    /**
      * @return whether fallback line spacing is enabled, {@code true} by default
      *
      * @see #setFallbackLineSpacing(boolean)
@@ -10683,7 +10737,8 @@
 
             if (hintBoring == UNKNOWN_BORING) {
                 hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
-                        isFallbackLineSpacingForBoringLayout(), mHintBoring);
+                        isFallbackLineSpacingForBoringLayout(),
+                        mMinimumFontMetrics, mHintBoring);
                 if (hintBoring != null) {
                     mHintBoring = hintBoring;
                 }
@@ -10732,7 +10787,8 @@
                         .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                         .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                                 mLineBreakStyle, mLineBreakWordStyle))
-                        .setUseBoundsForWidth(mUseBoundsForWidth);
+                        .setUseBoundsForWidth(mUseBoundsForWidth)
+                        .setMinimumFontMetrics(mMinimumFontMetrics);
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
                             .setEllipsizedWidth(ellipsisWidth);
@@ -10796,12 +10852,13 @@
                             mLineBreakStyle, mLineBreakWordStyle))
                     .setUseBoundsForWidth(mUseBoundsForWidth)
                     .setEllipsize(getKeyListener() == null ? effectiveEllipsize : null)
-                    .setEllipsizedWidth(ellipsisWidth);
+                    .setEllipsizedWidth(ellipsisWidth)
+                    .setMinimumFontMetrics(mMinimumFontMetrics);
             result = builder.build();
         } else {
             if (boring == UNKNOWN_BORING) {
                 boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir,
-                        isFallbackLineSpacingForBoringLayout(), mBoring);
+                        isFallbackLineSpacingForBoringLayout(), mMinimumFontMetrics, mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -10815,7 +10872,7 @@
                                 wantWidth, alignment, mSpacingMult, mSpacingAdd,
                                 boring, mIncludePad, null, wantWidth,
                                 isFallbackLineSpacingForBoringLayout(),
-                                mUseBoundsForWidth);
+                                mUseBoundsForWidth, mMinimumFontMetrics);
                     } else {
                         result = new BoringLayout(
                                 mTransformed,
@@ -10829,7 +10886,8 @@
                                 wantWidth,
                                 null,
                                 boring,
-                                mUseBoundsForWidth);
+                                mUseBoundsForWidth,
+                                mMinimumFontMetrics);
                     }
 
                     if (useSaved) {
@@ -10841,7 +10899,7 @@
                                 wantWidth, alignment, mSpacingMult, mSpacingAdd,
                                 boring, mIncludePad, effectiveEllipsize,
                                 ellipsisWidth, isFallbackLineSpacingForBoringLayout(),
-                                mUseBoundsForWidth);
+                                mUseBoundsForWidth, mMinimumFontMetrics);
                     } else {
                         result = new BoringLayout(
                                 mTransformed,
@@ -10855,7 +10913,8 @@
                                 ellipsisWidth,
                                 effectiveEllipsize,
                                 boring,
-                                mUseBoundsForWidth);
+                                mUseBoundsForWidth,
+                                mMinimumFontMetrics);
                     }
                 }
             }
@@ -10874,7 +10933,8 @@
                     .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                     .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                             mLineBreakStyle, mLineBreakWordStyle))
-                    .setUseBoundsForWidth(mUseBoundsForWidth);
+                    .setUseBoundsForWidth(mUseBoundsForWidth)
+                    .setMinimumFontMetrics(mMinimumFontMetrics);
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
                         .setEllipsizedWidth(ellipsisWidth);
@@ -11002,7 +11062,7 @@
 
             if (des < 0) {
                 boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir,
-                        isFallbackLineSpacingForBoringLayout(), mBoring);
+                        isFallbackLineSpacingForBoringLayout(), mMinimumFontMetrics, mBoring);
                 if (boring != null) {
                     mBoring = boring;
                 }
@@ -11042,7 +11102,8 @@
 
                 if (hintDes < 0) {
                     hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
-                            isFallbackLineSpacingForBoringLayout(), mHintBoring);
+                            isFallbackLineSpacingForBoringLayout(), mMinimumFontMetrics,
+                            mHintBoring);
                     if (hintBoring != null) {
                         mHintBoring = hintBoring;
                     }
@@ -11254,7 +11315,8 @@
                 .setTextDirection(getTextDirectionHeuristic())
                 .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                         mLineBreakStyle, mLineBreakWordStyle))
-                .setUseBoundsForWidth(mUseBoundsForWidth);
+                .setUseBoundsForWidth(mUseBoundsForWidth)
+                .setMinimumFontMetrics(mMinimumFontMetrics);
 
         final StaticLayout layout = layoutBuilder.build();
 
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 79b3b4f..4705dc5 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -23,7 +23,7 @@
 }
 
 flag {
-  name: "dimmer_refactor"
+  name: "introduce_smoother_dimmer"
   namespace: "windowing_frontend"
   description: "Refactor dim to fix flickers"
   bug: "295291019"
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index f77e962..65a2f4b 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -46,4 +46,5 @@
             in @nullable ImeTracker.Token statsToken);
     void onStylusHandwritingReady(int requestId, int pid);
     void resetStylusHandwriting(int requestId);
+    void switchKeyboardLayoutAsync(int direction);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 30ebbe2..792388d 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -431,4 +431,20 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#switchKeyboardLayoutAsync(int)}.
+     */
+    @AnyThread
+    public void switchKeyboardLayoutAsync(int direction) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.switchKeyboardLayoutAsync(direction);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 7e9cef7..e6b036c 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -58,6 +58,9 @@
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD;
@@ -276,7 +279,11 @@
 
     public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83;
 
-    private static final int LAST_CUJ = CUJ_LAUNCHER_UNFOLD_ANIM;
+    public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = 84;
+    public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = 85;
+    public static final int CUJ_PREDICTIVE_BACK_HOME = 86;
+
+    private static final int LAST_CUJ = CUJ_PREDICTIVE_BACK_HOME;
     private static final int NO_STATSD_LOGGING = -1;
 
     // Used to convert CujType to InteractionType enum value for statsd logging.
@@ -370,6 +377,12 @@
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY] =
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_TASK] =
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_HOME] =
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME;
     }
 
     private static class InstanceHolder {
@@ -473,6 +486,9 @@
             CUJ_IME_INSETS_HIDE_ANIMATION,
             CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
             CUJ_LAUNCHER_UNFOLD_ANIM,
+            CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY,
+            CUJ_PREDICTIVE_BACK_CROSS_TASK,
+            CUJ_PREDICTIVE_BACK_HOME,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -1108,6 +1124,12 @@
                 return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER";
             case CUJ_LAUNCHER_UNFOLD_ANIM:
                 return "LAUNCHER_UNFOLD_ANIM";
+            case CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY:
+                return "PREDICTIVE_BACK_CROSS_ACTIVITY";
+            case CUJ_PREDICTIVE_BACK_CROSS_TASK:
+                return "PREDICTIVE_BACK_CROSS_TASK";
+            case CUJ_PREDICTIVE_BACK_HOME:
+                return "PREDICTIVE_BACK_HOME";
         }
         return "UNKNOWN";
     }
diff --git a/core/jni/android_hardware_OverlayProperties.cpp b/core/jni/android_hardware_OverlayProperties.cpp
index 34ef7b3..5b95ee7 100644
--- a/core/jni/android_hardware_OverlayProperties.cpp
+++ b/core/jni/android_hardware_OverlayProperties.cpp
@@ -85,6 +85,18 @@
     return false;
 }
 
+static jlong android_hardware_OverlayProperties_createDefault(JNIEnv* env, jobject thiz) {
+    gui::OverlayProperties* overlayProperties = new gui::OverlayProperties;
+    gui::OverlayProperties::SupportedBufferCombinations combination;
+    combination.pixelFormats = {HAL_PIXEL_FORMAT_RGBA_8888};
+    combination.standards = {HAL_DATASPACE_BT709};
+    combination.transfers = {HAL_DATASPACE_TRANSFER_SRGB};
+    combination.ranges = {HAL_DATASPACE_RANGE_FULL};
+    overlayProperties->combinations.emplace_back(combination);
+    overlayProperties->supportMixedColorSpaces = true;
+    return reinterpret_cast<jlong>(overlayProperties);
+}
+
 // ----------------------------------------------------------------------------
 // Serialization
 // ----------------------------------------------------------------------------
@@ -150,6 +162,7 @@
             (void*) android_hardware_OverlayProperties_write },
     { "nReadOverlayPropertiesFromParcel", "(Landroid/os/Parcel;)J",
             (void*) android_hardware_OverlayProperties_read },
+    {"nCreateDefault", "()J", (void*) android_hardware_OverlayProperties_createDefault },
 };
 // clang-format on
 
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index f97d41b..262f5e8 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -42,13 +42,6 @@
         return NULL;
     }
 
-    // b/274058082: Pass a copy of the key character map to avoid concurrent
-    // access
-    std::shared_ptr<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap();
-    if (map != nullptr) {
-        map = std::make_shared<KeyCharacterMap>(*map);
-    }
-
     ScopedLocalRef<jstring> descriptorObj(env,
             env->NewStringUTF(deviceInfo.getIdentifier().descriptor.c_str()));
     if (!descriptorObj.get()) {
@@ -67,9 +60,14 @@
                                                                   ? layoutInfo->layoutType.c_str()
                                                                   : NULL));
 
+    std::shared_ptr<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap();
+    std::unique_ptr<KeyCharacterMap> mapCopy;
+    if (map != nullptr) {
+        mapCopy = std::make_unique<KeyCharacterMap>(*map);
+    }
     ScopedLocalRef<jobject> kcmObj(env,
                                    android_view_KeyCharacterMap_create(env, deviceInfo.getId(),
-                                                                       map));
+                                                                       std::move(mapCopy)));
     if (!kcmObj.get()) {
         return NULL;
     }
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index 7f69e22..a79e37a 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -48,7 +48,7 @@
 
 class NativeKeyCharacterMap {
 public:
-    NativeKeyCharacterMap(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map)
+    NativeKeyCharacterMap(int32_t deviceId, std::unique_ptr<KeyCharacterMap> map)
           : mDeviceId(deviceId), mMap(std::move(map)) {}
 
     ~NativeKeyCharacterMap() {
@@ -58,16 +58,18 @@
         return mDeviceId;
     }
 
-    inline const std::shared_ptr<KeyCharacterMap> getMap() const { return mMap; }
+    inline const std::unique_ptr<KeyCharacterMap>& getMap() const {
+        return mMap;
+    }
 
 private:
     int32_t mDeviceId;
-    std::shared_ptr<KeyCharacterMap> mMap;
+    std::unique_ptr<KeyCharacterMap> mMap;
 };
 
 jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId,
-                                            const std::shared_ptr<KeyCharacterMap> kcm) {
-    NativeKeyCharacterMap* nativeMap = new NativeKeyCharacterMap(deviceId, kcm);
+                                            std::unique_ptr<KeyCharacterMap> kcm) {
+    NativeKeyCharacterMap* nativeMap = new NativeKeyCharacterMap(deviceId, std::move(kcm));
     if (!nativeMap) {
         return nullptr;
     }
@@ -91,7 +93,7 @@
         return 0;
     }
 
-    std::shared_ptr<KeyCharacterMap> kcm = nullptr;
+    std::unique_ptr<KeyCharacterMap> kcm;
     // Check if map is a null character map
     if (parcel->readBool()) {
         kcm = KeyCharacterMap::readFromParcel(parcel);
@@ -99,7 +101,7 @@
             return 0;
         }
     }
-    NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm);
+    NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, std::move(kcm));
     return reinterpret_cast<jlong>(map);
 }
 
@@ -230,9 +232,9 @@
 }
 
 static jboolean nativeEquals(JNIEnv* env, jobject clazz, jlong ptr1, jlong ptr2) {
-    const std::shared_ptr<KeyCharacterMap>& map1 =
+    const std::unique_ptr<KeyCharacterMap>& map1 =
             (reinterpret_cast<NativeKeyCharacterMap*>(ptr1))->getMap();
-    const std::shared_ptr<KeyCharacterMap>& map2 =
+    const std::unique_ptr<KeyCharacterMap>& map2 =
             (reinterpret_cast<NativeKeyCharacterMap*>(ptr2))->getMap();
     if (map1 == nullptr || map2 == nullptr) {
         return map1 == map2;
diff --git a/core/jni/android_view_KeyCharacterMap.h b/core/jni/android_view_KeyCharacterMap.h
index be03353..a8aabd1 100644
--- a/core/jni/android_view_KeyCharacterMap.h
+++ b/core/jni/android_view_KeyCharacterMap.h
@@ -25,7 +25,7 @@
 
 /* Creates a KeyCharacterMap object from the given information. */
 extern jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId,
-                                                   const std::shared_ptr<KeyCharacterMap> kcm);
+                                                   std::unique_ptr<KeyCharacterMap> kcm);
 
 } // namespace android
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 178c0d0..9833598 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -126,7 +126,7 @@
     jfieldID height;
     jfieldID xDpi;
     jfieldID yDpi;
-    jfieldID refreshRate;
+    jfieldID peakRefreshRate;
     jfieldID vsyncRate;
     jfieldID appVsyncOffsetNanos;
     jfieldID presentationDeadlineNanos;
@@ -1232,7 +1232,7 @@
     env->SetFloatField(object, gDisplayModeClassInfo.xDpi, config.xDpi);
     env->SetFloatField(object, gDisplayModeClassInfo.yDpi, config.yDpi);
 
-    env->SetFloatField(object, gDisplayModeClassInfo.refreshRate, config.refreshRate);
+    env->SetFloatField(object, gDisplayModeClassInfo.peakRefreshRate, config.peakRefreshRate);
     env->SetFloatField(object, gDisplayModeClassInfo.vsyncRate, config.vsyncRate);
     env->SetLongField(object, gDisplayModeClassInfo.appVsyncOffsetNanos, config.appVsyncOffset);
     env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos,
@@ -2396,7 +2396,7 @@
     gDisplayModeClassInfo.height = GetFieldIDOrDie(env, modeClazz, "height", "I");
     gDisplayModeClassInfo.xDpi = GetFieldIDOrDie(env, modeClazz, "xDpi", "F");
     gDisplayModeClassInfo.yDpi = GetFieldIDOrDie(env, modeClazz, "yDpi", "F");
-    gDisplayModeClassInfo.refreshRate = GetFieldIDOrDie(env, modeClazz, "refreshRate", "F");
+    gDisplayModeClassInfo.peakRefreshRate = GetFieldIDOrDie(env, modeClazz, "peakRefreshRate", "F");
     gDisplayModeClassInfo.vsyncRate = GetFieldIDOrDie(env, modeClazz, "vsyncRate", "F");
     gDisplayModeClassInfo.appVsyncOffsetNanos =
             GetFieldIDOrDie(env, modeClazz, "appVsyncOffsetNanos", "J");
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index cd951cb..5037239 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Toeganklikheidgebruik"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skerm"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Laat ’n metgeselapp toe om voorgronddienste van agtergrond af te begin"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoon is beskikbaar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoon is geblokkeer"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan nie na skerm weerspieël nie"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gebruik ’n ander kabel en probeer weer"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel steun dalk nie skerms nie"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Jou USB-C-kabel koppel dalk nie behoorlik aan skerms nie"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is aan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans albei skerms om inhoud te wys"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 42ba598..9a8bb62 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ማጉላት"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"የተደራሽነት አጠቃቀም"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ማሳያ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"አጃቢ መተግበሪያ ከዳራ የፊት አገልግሎቶችን እንዲጀምር ያስችላል።"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ማይክሮፎን ይገኛል"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ማይክሮፎን ታግዷል"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ወደ ማሳያ ማንጸባረቅ አልተቻለም"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"የተለየ ገመድ ይጠቀሙ እና እንደገና ይሞክሩ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ገመድ ማሳያዎችን ላይደግፍ ይችላል"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"የእርስዎ USB-C ገመድ ከማሳያዎች ጋር በትክክል ላይገናኝ ይችላል"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ገፅ በርቷል"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ይዘትን ለማሳየት ሁለቱንም ማሳያዎች እየተጠቀመ ነው"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 68d7ff4..f6d7c64 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -294,6 +294,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"التكبير"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"استخدام \"أدوات تسهيل الاستخدام\""</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"الشاشة"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string>
@@ -2337,6 +2338,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"يسمح هذا الإذن للتطبيق المصاحب ببدء الخدمات التي تعمل في المقدّمة من الخلفية."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"الميكروفون متاح."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"تم حظر الميكروفون."</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"يتعذّر إجراء نسخ مطابق لمحتوى جهازك إلى الشاشة"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"يُرجى استخدام كابل آخر وإعادة المحاولة."</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"قد لا يتوافق الكابل مع الشاشات"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏قد لا يتم توصيل الكابل المزوَّد بمنفذ USB-C بالشاشات بشكل صحيح."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‏ميزة Dual Screen مفعّلة"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"يستخدم \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" كلتا الشاشتين لعرض المحتوى."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index ba3e756..df4f28a 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰী খৰচ কৰা এপ্‌সমূহ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"সাধ্য সুবিধাৰ ব্যৱহাৰ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ডিছপ্লে’"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰী ব্যৱহাৰ কৰি আছে"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰী ব্যৱহাৰ কৰি আছে"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰী আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে সবিশেষ জানিবলৈ টিপক"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"এটা সহযোগী এপক নেপথ্যৰ পৰা অগ্ৰভূমি সেৱাসমূহ আৰম্ভ কৰিবলৈ দিয়ে।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"মাইক্ৰ’ফ’নটো উপলব্ধ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"মাইক্ৰ’ফ’নটো অৱৰোধ কৰি থোৱা আছে"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"সংযুক্ত ডিছপ্লে’ উপলব্ধ নহয়"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"অন্য এডাল কে’বল ব্যৱহাৰ কৰি পুনৰ চেষ্টা কৰক"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"কে’বলে ডিছপ্লে’ সমৰ্থন নকৰিবও পাৰে"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"আপোনাৰ USB-C কে’বল ডিছপ্লে’ৰ সৈতে সঠিকভাৱে সংযোগ নহ’বও পাৰে"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen অন আছে"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ সমল দেখুৱাবলৈ দুয়োখন ডিছপ্লে’ ব্যৱহাৰ কৰি আছে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 4124dfa..8bfd8b5 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Böyütmə"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Əlçatımlılıq istifadəsi"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Displey"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Kompanyon tətbiqinə ön fon xidmətlərini arxa fondan başlatmaq icazəsi verir."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon əlçatandır"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon blok edilib"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Displeydə əks etdirmək olmur"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Başqa kabel istifadə edin və yenidən cəhd edin"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel displeyləri dəstəkləməyə bilər"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabeli displeylərə düzgün qoşulmaya bilər"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"İkili ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"İkili ekran aktivdir"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> məzmunu göstərmək üçün hər iki displeydən istifadə edir"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3fd8dcb..48b5c02 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećanje"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Korišćenje Pristupačnosti"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string>
@@ -314,7 +315,7 @@
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Muzika i zvuk"</string>
     <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"pristup muzici i audio sadržaju na uređaju"</string>
     <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Slike i video snimci"</string>
-    <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"pristup slikama i video snimcima na uređaju"</string>
+    <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"pristup slikama i videima na uređaju"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snima zvuk"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Fizičke aktivnosti"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Dozvoljava pratećoj aplikaciji da pokrene usluge u prvom planu iz pozadine."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Preslikavanje na ekran nije moguće"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrebite drugi kabl i probajte ponovo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabl ne podržava ekrane"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabl se ne povezuje pravilno sa ekranima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je uključen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 715aad3..12effa0 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Павелічэнне"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Выкарыстанне спецыяльных магчымасцей"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Дысплэй"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Спадарожная праграма зможа запускаць актыўныя сэрвісы з фонавага рэжыму."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Мікрафон даступны"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Мікрафон заблакіраваны"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не ўдалося прадубліраваць змесціва на дысплэі"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Паспрабуйце скарыстаць іншы кабель"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Магчыма, кабель несумяшчальны з дысплэямі"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Магчыма, кабель USB-C не падыходзіць да дысплэяў"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Уключана функцыя Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" выкарыстоўвае абодва экраны для паказу змесціва"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9dd971c..d18e4bc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Използване на услугите за достъпност"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Дисплей"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Разрешава на дадено придружаващо приложение да стартира услуги на преден план, докато се изпълнява на заден план."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофонът е налице"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофонът е блокиран"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не може да се копира огледално на дисплея"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Използвайте друг кабел и опитайте отново"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабелът не поддържа дисплеи"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабелът ви може да не се свързва правилно с дисплеи"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Функцията Dual Screen е включена"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва и двата екрана, за да показва съдържание"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 6f879e4..859f37d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখা"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"অ্যাক্সেসিবিলিটি সংক্রান্ত ব্যবহার"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ডিসপ্লে"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"কম্প্যানিয়ন অ্যাপকে, ব্যাকগ্রাউন্ড থেকে ফোরগ্রাউন্ড পরিষেবা চালু করার অনুমতি দেয়।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"মাইক্রোফোন উপলভ্য আছে"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"মাইক্রোফোন ব্লক করা হয়েছে"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ডিসপ্লে মিরর করা যাচ্ছে না"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"অন্য কোনও কেবল ব্যবহার করে আবার চেষ্টা করুন"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"কেবল, ডিসপ্লের সাথে কাজ নাও করতে পারে"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"আপনার USB-C কেবল, ডিসপ্লেতে সঠিকভাবে কানেক্ট নাও হতে পারে"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen চালু করা আছে"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"কন্টেন্ট দেখানোর জন্য <xliff:g id="APP_NAME">%1$s</xliff:g> দুটি ডিসপ্লে ব্যবহার করছে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index b0f1905..8e9fe9c 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećavanje"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Korištenje pristupačnosti"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Dozvoljava pratećoj aplikaciji da iz pozadine pokrene usluge u prvom planu."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nije moguće preslikati na ekran"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrijebite drugi kabl i pokušajte ponovo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabl možda neće podržavati ekrane"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabl se možda neće pravilno povezati s ekranima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je uključen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index be95847..dacdbf1 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliació"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Ús de les funcions d\'accessibilitat"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Pantalla"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permet que una aplicació complementària iniciï serveis en primer pla des d\'un segon pla."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micròfon està disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micròfon està bloquejat"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No es pot projectar a la pantalla"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilitza un altre cable i torna-ho a provar"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"És possible que el cable no sigui compatible amb pantalles"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"És possible que el teu cable USB-C no es connecti correctament a les pantalles"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Pantalla dual"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La pantalla dual està activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> està utilitzant les dues pantalles per mostrar contingut"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 32cff76..29e00fa 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zvětšení"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Využití přístupnosti"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Displej"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Umožňuje doprovodné aplikaci spouštět z pozadí služby v popředí."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupný"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je zablokován"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nelze zrcadlit na displej"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Použijte jiný kabel a zkuste to znovu"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel možná nepodporuje displeje"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Váš kabel USB-C se možná nedokáže správně připojit k displejům"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Je zapnutá funkce Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> používá k zobrazení obsahu oba displeje"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 75bf365..87703cd 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørrelse"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Brug af hjælpefunktioner"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skærm"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tillader, at en medfølgende app kan starte tjenester i forgrunden via tilladelser til tjenester i baggrunden."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen er tilgængelig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen er blokeret"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Det er ikke muligt at spejle til skærmen"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Brug et andet kabel, og prøv igen"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablet understøtter muligvis ikke skærme"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Dit USB-C-kabel kan muligvis ikke sluttes korrekt til skærmene"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen er aktiveret"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger begge skærme til at vise indhold"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e087fe2..3faf328 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergrößerung"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Nutzung der Bedienungshilfen"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ermöglicht einer Companion-App, Dienste im Vordergrund aus dem Hintergrund zu starten."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon ist verfügbar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon ist blockiert"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kann nicht auf das Display gespiegelt werden"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Verwende ein anderes Kabel und versuch es noch einmal"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel unterstützt eventuell keine Bildschirme"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Dein USB-C-Kabel ist möglicherweise nicht zum Verbinden von Bildschirmen geeignet"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ist aktiviert"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> nutzt zum Anzeigen von Inhalten beide Displays"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9b713c99..af53ddf 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Μεγιστοποίηση"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Χρήση προσβασιμότητας"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Οθόνη"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string>
@@ -1376,7 +1377,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Εντοπίστηκε αναλογικό αξεσουάρ ήχου"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Η συνδεδεμένη συσκευή δεν είναι συμβατή με αυτό το τηλέφωνο. Πατήστε για να μάθετε περισσότερα."</string>
     <string name="adb_active_notification_title" msgid="408390247354560331">"Συνδέθηκε ο εντοπ. σφαλμ. USB"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"Πατήστε για απενεργ. εντοπ./διόρθ. σφαλμ. USB"</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"Πατήστε για απενεργ. εντοπ. σφαλμ. USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Επιλογή για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Συνδέθηκε ο ασύρματος εντοπισμός σφαλμάτων"</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Πατήστε, για να απενεργοποιήσετε τον ασύρματο εντοπισμό σφαλμάτων"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Επιτρέπει σε μια συνοδευτική εφαρμογή να εκκινεί υπηρεσίες στο προσκήνιο από το παρασκήνιο."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Το μικρόφωνο είναι διαθέσιμο"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Το μικρόφωνο έχει αποκλειστεί"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Δεν είναι δυνατός ο κατοπτρισμός στην οθόνη"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Χρησιμοποιήστε άλλο καλώδιο και δοκιμάστε ξανά"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Το καλώδιο μπορεί να μην υποστηρίζει οθόνες"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Το καλώδιο USB-C που έχετε ίσως να μην μπορεί να συνδεθεί σωστά σε οθόνες"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Διπλή οθόνη"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Η λειτουργία διπλής οθόνης είναι ενεργή"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Η εφαρμ. <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί και τις 2 οθόνες για εμφάνιση περιεχ."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index bc231f5..8917a82 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Accessibility usage"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 29f4c78..5a0ed85 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Accessibility usage"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use a different cable and try again"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5576054..bcf0790 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Accessibility usage"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ea95a513..7ebffc6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Accessibility usage"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index c09e6ce..b739768 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎Apps consuming battery‎‏‎‎‏‎"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎Magnification‎‏‎‎‏‎"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‎‎Accessibility usage‎‏‎‎‏‎"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎Display‎‏‎‎‏‎"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using battery‎‏‎‎‏‎"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NUMBER">%1$d</xliff:g>‎‏‎‎‏‏‏‎ apps are using battery‎‏‎‎‏‎"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎Tap for details on battery and data usage‎‏‎‎‏‎"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎Allows a companion app to start foreground services from background.‎‏‎‎‏‎"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎Microphone is available‎‏‎‎‏‎"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Microphone is blocked‎‏‎‎‏‎"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎Can\'t mirror to display‎‏‎‎‏‎"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎Use a different cable and try again‎‏‎‎‏‎"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎Cable may not support displays‎‏‎‎‏‎"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎Your USB-C cable may not connect to displays properly‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎Dual screen‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎Dual screen is on‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using both displays to show content‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 723f833..ca9ff13 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uso de accesibilidad"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Pantalla"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que una aplicación complementaria inicie servicios en primer plano desde el segundo plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micrófono está disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micrófono está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No se puede duplicar la pantalla"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa un cable diferente y vuelve a intentarlo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Es posible que el cable no admita pantallas"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Es posible que el cable USB-C no se conecte a las pantallas de manera adecuada"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La función Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas pantallas para mostrar contenido"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 79c6e26..97b1888 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uso de accesibilidad"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Pantalla"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que una aplicación complementaria inicie servicios en primer plano desde el segundo plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micrófono está disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micrófono está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No se puede proyectar a la pantalla"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa otro cable y vuelve a intentarlo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"El cable puede no ser compatible con pantallas"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Puede que tu cable USB‑C no sea adecuado para conectarse a pantallas"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La función Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas pantallas para mostrar contenido"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 67c20f7..4a8666e 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurendus"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Juurdepääsetavuse kasutus"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekraan"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lubab kaasrakendusel taustal käivitada esiplaanil olevaid teenuseid."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon on saadaval"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon on blokeeritud"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ei saa ekraanile peegeldada"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Kasutage teist kaablit ja proovige uuesti"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kaabel ei pruugi ekraane toetada"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Teie USB-C-kaabel ei pruugi ekraanidega õigesti ühendust luua"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screeni režiim on sisse lülitatud"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab sisu kuvamiseks mõlemat ekraani"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2150324..a163ed8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Lupa"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Erabilerraztasun-hobespenak"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Pantaila"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datu-erabilerari buruzko xehetasunak ikusteko"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Aurreko planoko zerbitzuak atzeko planotik abiarazteko baimena ematen die aplikazio osagarriei."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Erabilgarri dago mikrofonoa"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Blokeatuta dago mikrofonoa"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ezin da islatu pantailan"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Erabili beste kable bat eta saiatu berriro"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Baliteke kablea pantailekin bateragarria ez izatea"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Baliteke USB-C kablea behar bezala ez konektatzea pantailetara"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen aktibatuta dago"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bi pantailak erabiltzen ari da edukia erakusteko"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index de1ba1a..c5a2ee6 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامه‌های مصرف‌کننده باتری"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"درشت‌نمایی"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"کاربرد دسترس‌پذیری"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"نمایشگر"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"به برنامه همراه اجازه می‌دهد سرویس‌های پیش‌نما را از پس‌زمینه راه‌اندازی کند."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"میکروفون دردسترس است"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"میکروفون مسدود شد"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"بازتاب دادن به نمایشگر ممکن نبود"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"از کابل دیگری استفاده کنید و دوباره امتحان کنید"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"شاید کابل از نمایشگر پشتیبانی نکند"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏کابل USB-C شما ممکن است به‌درستی به نمایشگرها وصل نشود"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"‫Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‏‫Dual Screen روشن است"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"‫<xliff:g id="APP_NAME">%1$s</xliff:g> از هر دو نمایشگر برای نمایش محتوا استفاده می‌کند"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 22d48e2..4a08b90 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurennus"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Esteetön käyttö"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Näyttö"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Sallii kumppanisovelluksen aloittaa etualan palveluja taustalla."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoni on käytettävissä"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoni on estetty"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Näytön peilaaminen ei onnistu"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Käytä eri johtoa ja yritä uudelleen"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Johto ei ehkä tue näyttöjä"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C-johtosi ei ehkä yhdisty näyttöihin kunnolla"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Kaksoisnäyttö"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Kaksoisnäyttö on päällä"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää molempia näyttöjä sisällön näyttämiseen"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 928bf77..1b637db 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Usage des fonctionnalités d\'accessibilité"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Écran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permet à une application compagnon en arrière-plan de lancer des services d\'avant-plan."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Le microphone est accessible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Le microphone est bloqué"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Impossible de dupliquer l\'écran"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilisez un câble différent et réessayez"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Le câble peut ne pas être compatible avec les écrans"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Votre câble USB-C peut ne pas se connecter correctement aux écrans"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen activé"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise les deux écrans pour afficher le contenu"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d7d29a4..4f8de0c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Utilisation de l\'accessibilité"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Écran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Autorise une application associée à lancer des services de premier plan à partir de l\'arrière-plan."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Le micro est disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Le micro est bloqué"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Duplication impossible"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilisez un autre câble et réessayez"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Le câble n\'est peut-être pas compatible avec les écrans"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Votre câble USB-C n\'est peut-être pas connecté correctement à l\'écran"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Double écran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Double écran activé"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise les deux écrans pour afficher du contenu"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e2073fb..b25cfcb 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uso de accesibilidade"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Pantalla"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que unha aplicación complementaria, desde un segundo plano, inicie servizos en primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O micrófono está dispoñible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O micrófono está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Non se pode proxectar contido na pantalla"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Cambia de cable e téntao de novo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Pode que o cable non sexa compatible con pantallas"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"O teu cable USB-C pode que non se conecte ás pantallas de maneira adecuada"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas as pantallas para mostrar contido"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 82b4a0d..fae5ebc 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"મોટું કરવાની સુવિધા"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ઍક્સેસિબિલિટી વપરાશ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ડિસ્પ્લે"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"સાથી ઍપને બૅકગ્રાઉન્ડમાંથી ફૉરગ્રાઉન્ડ સેવાઓ શરૂ કરવાની મંજૂરી આપે છે."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"માઇક્રોફોન ઉપલબ્ધ છે"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"માઇક્રોફોનને બ્લૉક કરવામાં આવ્યો છે"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ડિસ્પ્લે પર મિરર કરી શકાતું નથી"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"બીજા કોઈ કેબલનો ઉપયોગ કરો અને ફરી પ્રયાસ કરો"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"શક્ય છે કે કેબલ કદાચ ડિસ્પ્લેને સપોર્ટ ન આપતો હોય"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"તમારો USB-C કેબલ કદાચ ડિસ્પ્લે સાથે યોગ્ય રીતે કનેક્ટ ન થાય"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ચાલુ છે"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"કન્ટેન્ટ બતાવવા માટે <xliff:g id="APP_NAME">%1$s</xliff:g> બન્ને ડિસ્પ્લેનો ઉપયોગ કરી રહી છે"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1f3a377..d4eb380 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ज़ूम करने की सुविधा"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"सुलभता सुविधाओं का इस्तेमाल"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"डिसप्ले"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"इससे साथी ऐप्लिकेशन को बैकग्राउंड में फ़ोरग्राउंड सेवाएं चलाने की अनुमति मिलती है."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"माइक्रोफ़ोन इस्तेमाल किया जा सकता है"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"माइक्रोफ़ोन को ब्लॉक किया गया है"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिसप्ले का कॉन्टेंट नहीं दिखाया जा सकता"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"कोई दूसरा केबल इस्तेमाल करके फिर से कोशिश करें"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ऐसा हो सकता है कि केबल, डिसप्ले के साथ ठीक से काम न करे"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ऐसा हो सकता है कि यूएसबी-सी केबल, डिसप्ले के साथ ठीक से कनेक्ट न हो पाए"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen की सुविधा चालू है"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>, कॉन्टेंट दिखाने के लिए दोनों स्क्रीन का इस्तेमाल कर रहा है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 389a956..81ac641 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povećavanje"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Upotreba pristupačnosti"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Zaslon"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Popratnoj aplikaciji omogućuje da iz pozadine pokrene usluge u prednjem planu."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Zrcaljenje na zaslon nije moguće"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrijebite drugi kabel i pokušajte ponovno"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel možda ne podržava zaslone"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Vaš USB-C kabel možda nije ispravno povezan sa zaslonima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvostruki zaslon"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Uključen je dvostruki zaslon"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> upotrebljava oba zaslona za prikazivanje sadržaja"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4bce83b..9a389db 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Nagyítás"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Kisegítő lehetőségek használata"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Kijelző"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lehetővé teszi a társalkalmazások számára, hogy előtérben futó szolgáltatásokat indítsanak a háttérből."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"A mikrofon rendelkezésre áll"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"A mikrofon le van tiltva"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nem lehet tükrözni a kijelzőre"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Használjon másik kábelt, és próbálja újra"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Előfordulhat, hogy a kábel nem támogatja a kijelzőket"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Előfordulhat, hogy az USB-C kábellel nem csatlakoztathatók megfelelően a kijelzők"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A Dual Screen funkció be van kapcsolva"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> mindkét kijelzőt használja a tartalmak megjelenítésére"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index e74ec54..ccea0cc 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Խոշորացում"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Հատուկ գործառույթների օգտագործում"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Էկրան"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Թույլատրում է ուղեկցող հավելվածին ակտիվ ծառայություններ գործարկել ֆոնային ռեժիմից։"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Խոսափողը հասանելի է"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Խոսափողն արգելափակված է"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Չհաջողվեց հայելապատճենել էկրանին"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Օգտագործեք այլ մալուխ և նորից փորձեք"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Մալուխը կարող է համատեղելի չլինել էկրանների հետ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Հնարավոր է՝ USB-C մալուխը սխալ է միացված էկրանին"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen-ը միացված է"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն օգտագործում է երկու էկրանները"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index dc0993e..47bbefd 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Penggunaan aksesibilitas"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Layar"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Mengizinkan aplikasi pendamping memulai layanan latar depan dari latar belakang."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon tersedia"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon diblokir"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Tidak dapat mencerminkan ke layar"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gunakan kabel lain dan coba lagi"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel mungkin tidak mendukung layar"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C mungkin tidak terhubung dengan benar ke layar"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen aktif"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggunakan kedua layar untuk menampilkan konten"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2af8969..f666308 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Stækkun"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Aðgengisnotkun"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skjár"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Leyfir fylgiforriti að ræsa forgrunnsþjónustur úr bakgrunni."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Hljóðnemi er í boði"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Lokað er fyrir hljóðnemann"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ekki er hægt að spegla á skjá"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Notaðu aðra snúru og reyndu aftur"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Ekki er víst að snúran styðji skjái"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ekki er víst að USB-C-snúran tengist skjám á réttan hátt"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tveir skjáir"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Kveikt er á tveimur skjám"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> er að nota báða skjái til að sýna efni"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7ea502c..e6bc552 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"App che consumano la batteria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ingrandimento"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Utilizzo dell\'accessibilità"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> sta consumando la batteria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> app stanno consumando la batteria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Consente a un\'app complementare di avviare servizi in primo piano dal background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfono disponibile"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfono bloccato"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Impossibile eseguire il mirroring al display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa un altro cavo e riprova"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Il cavo potrebbe non supportare i display"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Il cavo USB-C potrebbe non collegarsi correttamente ai display"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Doppio schermo"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Doppio schermo attivo"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> sta usando entrambi i display per mostrare contenuti"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 22cbab2..53ec382 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"הגדלה"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"שימוש בנגישות"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"מסך"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"אפשר להקיש כדי לקבל פרטים על צריכה של נתונים וסוללה"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ההרשאה הזו מאפשרת לאפליקציה נלווית להפעיל מהרקע שירותים שפועלים בחזית."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"המיקרופון זמין"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"המיקרופון חסום"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"לא ניתן לשקף למסך"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"צריך להשתמש בכבל שונה ולנסות שוב"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"יכול להיות שהכבל לא תומך במסכים"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏יכול להיות שכבל ה-USB-C לא יתחבר למסכים כמו שצריך"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"מצב שני מסכים"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"מצב שני מסכים מופעל"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בשני המסכים כדי להציג תוכן"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 06b3445..961a8da87 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ユーザー補助の使用"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ディスプレイ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」がバッテリーを使用しています"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップしてバッテリーやデータの使用量を確認"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"バックグラウンドからのフォアグラウンド サービスの起動をコンパニオン アプリに許可します。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"マイクを利用できます"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"マイクがブロックされています"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ディスプレイにミラーリングできません"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"別のケーブルでもう一度お試しください"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ケーブルはディスプレイに対応していない可能性があります"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C ケーブルがディスプレイに正しく接続されていない可能性があります"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"デュアル スクリーン"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"デュアル スクリーン: ON"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>は 2 画面でコンテンツを表示しています"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c8f6621f4..27f596b 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ბატარეის მხარჯავი აპები"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"გადიდება"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"მარტივი წვდომის გამოყენება"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ეკრანი"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ბატარეას"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"ბატარეას <xliff:g id="NUMBER">%1$d</xliff:g> აპი იყენებს"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"საშუალებას აძლევს კომპანიონ აპს, რომ გაუშვას უპირატესი სერვისები ფონური რეჟიმიდან."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"მიკროფონი ხელმისაწვდომია"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"მიკროფონი დაბლოკილია"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ეკრანზე არეკვლა შეუძლებელია"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"გამოიყენეთ სხვა კაბელი და ცადეთ ხელახლა"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"კაბელს შეიძლება არ ჰქონდეს ეკრანების მხარდაჭერა"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"თქვენი USB-C კაბელი შეიძლება სათანადოდ არ უკავშირდებოდეს ეკრანებს"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ორმაგი ეკრანი"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ორმაგი ეკრანი ჩართულია"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ორივე ეკრანს შინაარსის საჩვენებლად"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 1272c24..1faea61 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ұлғайту"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Арнайы мүмкіндіктерді қолдану"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Дисплей"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Қосымша қолданбаға экрандық режимдегі қызметтерді фоннан іске қосуға рұқсат беріледі."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон қолжетімді."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон блокталған."</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Дисплейге көшірмені көрсету мүмкін емес"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Басқа кабельмен әрекетті қайталап көріңіз."</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель дисплейлерді қолдамауы мүмкін"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабелі дисплейлерге дұрыс жалғанбаған болуы мүмкін."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen функциясы қосулы"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы контентті көрсету үшін екі дисплейді де пайдаланады."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 807761e..470c39e 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែល​កំពុងប្រើថ្ម"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ការពង្រីក"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ការប្រើប្រាស់​ភាពងាយស្រួល"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ផ្ទាំងអេក្រង់"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"អនុញ្ញាតឱ្យកម្មវិធីដៃគូចាប់ផ្តើមសេវាកម្មផ្ទៃខាងមុខពីផ្ទៃខាងក្រោយ។"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"អាចប្រើ​មីក្រូហ្វូនបាន"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"មីក្រូហ្វូនត្រូវ​បានទប់ស្កាត់"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"មិនអាចបញ្ចាំងទៅផ្ទាំងអេក្រង់បានទេ"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ប្រើខ្សែផ្សេង រួចព្យាយាមម្តងទៀត"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ខ្សែប្រហែលជាមិនអាចប្រើជាមួយផ្ទាំងអេក្រង់បានទេ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ខ្សែ USB-C របស់អ្នក​ប្រហែលជា​មិនអាចភ្ជាប់​ផ្ទាំងអេក្រង់​បានត្រឹមត្រូវទេ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"អេក្រង់ពីរ"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"អេក្រង់ពីរត្រូវបានបើក"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើផ្ទាំងអេក្រង់ទាំងពីរដើម្បីបង្ហាញខ្លឹមសារ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 742dfbb..e2f24f6 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ಪ್ರವೇಶಿಸುವಿಕೆಯ ಬಳಕೆ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ಡಿಸ್‌ಪ್ಲೇ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಹಿನ್ನೆಲೆಯಿಂದ ಪ್ರಾರಂಭಿಸಲು ಕಂಪ್ಯಾನಿಯನ್ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ಮೈಕ್ರೊಫೋನ್ ಲಭ್ಯವಿದೆ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ಡಿಸ್‌ಪ್ಲೇಗೆ ಪ್ರತಿಬಿಂಬಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ಬೇರೆ ಕೇಬಲ್ ಬಳಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ಡಿಸ್‌ಪ್ಲೇಗಳನ್ನು ಕೇಬಲ್ ಬೆಂಬಲಿಸದಿರಬಹುದು"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ನಿಮ್ಮ USB-C ಕೇಬಲ್ ಡಿಸ್‌ಪ್ಲೇಗಳಿಗೆ ಸರಿಯಾಗಿ ಕನೆಕ್ಟ್ ಆಗದಿರಬಹುದು"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ಆನ್ ಆಗಿದೆ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ಕಂಟೆಂಟ್‌ ಅನ್ನು ತೋರಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಎರಡೂ ಡಿಸ್‌ಪ್ಲೇಗಳನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index d2b6dc8..0608283 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"확대"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"접근성 사용"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"디스플레이"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"호환 앱이 백그라운드에서 포그라운드 서비스를 시작할 수 있게 허용합니다."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"마이크 사용 가능"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"마이크가 차단됨"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"디스플레이에 미러링할 수 없음"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"다른 케이블을 사용하여 다시 시도해 보세요."</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"디스플레이를 지원하지 않는 케이블일 수 있음"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"사용 중인 USB-C 케이블이 디스플레이에 제대로 연결되지 않을 수 있습니다."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen 켜짐"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 두 화면을 모두 사용하여 콘텐츠를 표시합니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 56c0696..853221e 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Чоңойтуу"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Атайын мүмкүнчүлүктөрдүн колдонулушу"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Экран"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
@@ -1384,7 +1385,7 @@
     <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Сыноо программасынын режими иштетилди"</string>
     <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Сыноо программасынын режимин өчүрүү үчүн баштапкы параметрлерге кайтарыңыз."</string>
     <string name="console_running_notification_title" msgid="6087888939261635904">"Сериялык консоль иштетилди"</string>
-    <string name="console_running_notification_message" msgid="7892751888125174039">"Майнаптуулугуна таасири тиет. Аны өчүрүү үчүн операциялык тутумду жүктөгүчтү текшериңиз."</string>
+    <string name="console_running_notification_message" msgid="7892751888125174039">"Майнаптуулугуна таасири тиет. Өчүрүү үчүн операциялык тутумду жүктөгүчтү текшериңиз."</string>
     <string name="mte_override_notification_title" msgid="4731115381962792944">"Cынамык MTE иштетилди"</string>
     <string name="mte_override_notification_message" msgid="2441170442725738942">"Иштин майнаптуулугуна жана туруктуулугуна кедергиси тийиши мүмкүн. Өчүрүү үчүн түзмөктү өчүрүп-күйгүзүңүз. Эгер arm64.memtag.bootctl аркылуу иштетилген болсо, алдын ала \"none\" маанисин орнотуңуз."</string>
     <string name="usb_contaminant_detected_title" msgid="4359048603069159678">"USB портунда суюктук же урандылар бар"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Көмөкчү колдонмого активдүү кызматтарды фондо иштетүүгө уруксат берет."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон жеткиликтүү"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон бөгөттөлгөн"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Экранга күзгүдөй чагылдыруу мүмкүн эмес"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Башка кабелди колдонуп, кайра аракет кылыңыз"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель дисплейлерди колдоого албашы мүмкүн"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабели дисплейлерге туура туташпашы мүмкүн"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Кош экран"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen күйүк"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> контентти эки түзмөктө тең көрсөтүүдө"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 8892f60..c743fc0 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ການຂະຫຍາຍ"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ການໃຊ້ການຊ່ວຍເຂົ້າເຖິງ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ຈໍສະແດງຜົນ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ອະນຸຍາດຈາກເບື້ອງຫຼັງໃຫ້ແອັບຊ່ວຍເຫຼືອເລີ່ມໃຊ້ບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າ."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ໄມໂຄຣໂຟນພ້ອມໃຫ້ນຳໃຊ້"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ໄມໂຄຣໂຟນຖືກບລັອກໄວ້"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ບໍ່ສາມາດສະທ້ອນໄປຫາຈໍສະແດງຜົນໄດ້"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ກະລຸນາໃຊ້ສາຍອື່ນແລ້ວລອງໃໝ່"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ສາຍອາດບໍ່ຮອງຮັບຈໍສະແດງຜົນ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ສາຍ USB-C ຂອງທ່ານອາດບໍ່ໄດ້ເຊື່ອມຕໍ່ກັບຈໍສະແດງຜົນຢ່າງຖືກຕ້ອງ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ໜ້າຈໍຄູ່"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ເປີດ Dual Screen ຢູ່"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ຈໍສະແດງຜົນທັງສອງເພື່ອສະແດງເນື້ອຫາ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8b4ff97..ff665c5 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Didinimas"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Pritaikomumo funkcijų naudojimas"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekranas"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Leidžiama papildomai programai paleisti priekinio plano paslaugas fone."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonas pasiekiamas"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonas užblokuotas"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Negalima bendrinti ekrano vaizdo ekrane"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Naudokite kitą laiką ir bandykite dar kartą"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Laidas gali nepalaikyti ekranų"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Gali būti, kad USB-C laidu nepavyksta tinkamai prisijungti prie ekranų"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Įjungta „Dual Screen“"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja abu ekranus turiniui rodyti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index c509378..4d369aa 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Palielinājums"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Pieejamības lietojums"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Displejs"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ļauj palīglietotnei sākt priekšplāna pakalpojumus no fona."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofons ir pieejams."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofons ir bloķēts."</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nevar spoguļot displeju"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Izmantojiet citu vadu un mēģiniet vēlreiz."</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Iespējams, vads neatbalsta displejus"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Iespējams, jūsu USB-C vads nevarēs nodrošināt pareizu savienojumu ar displejiem."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen režīms"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Ieslēgts Dual Screen režīms"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> satura rādīšanai izmanto abus displejus."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 109e967..29c9de8 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Зголемување"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Користење на пристапноста"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Екран"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот интернет"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозволува придружна апликација да започне услуги во преден план од заднината."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофонот е достапен"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофонот е блокиран"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не може да се отсликува за прикажување"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Користете друг кабел и обидете се повторно"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабелот можеби не поддржува екрани"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Кабелот USB-C можеби нема да се поврзе правилно со екраните"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Вклучен е Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ги користи двата екрани за да прикажува содржини"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9ccf8b5..46587ee 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"മാഗ്നിഫിക്കേഷൻ"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ഉപയോഗസഹായി ഉപയോഗം"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ഡിസ്‌പ്ലേ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"പശ്ചാത്തലത്തിൽ നിന്ന് ഫോർഗ്രൗണ്ട് സേവനങ്ങൾ ആരംഭിക്കാൻ സഹകാരി ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"മൈക്രോഫോൺ ലഭ്യമാണ്"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"മൈക്രോഫോൺ ബ്ലോക്ക് ചെയ്‌തു"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ഡിസ്‌പ്ലേയിലേക്ക് മിറർ ചെയ്യാനാകില്ല"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"മറ്റൊരു കേബിൾ ഉപയോഗിച്ച് വീണ്ടും ശ്രമിക്കുക"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"കേബിൾ, ഡിസ്പ്ലേകളെ പിന്തുണച്ചേക്കില്ല"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"നിങ്ങളുടെ USB-C കേബിൾ, ഡിസ്‌പ്ലേകളിലേക്ക് ശരിയായി കണക്റ്റ് ആയേക്കില്ല"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ഡ്യുവൽ സ്ക്രീൻ"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ഡ്യുവൽ സ്ക്രീൻ ഓണാണ്"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ഉള്ളടക്കം കാണിക്കാൻ <xliff:g id="APP_NAME">%1$s</xliff:g> രണ്ട് ഡിസ്പ്ലേകളും ഉപയോഗിക്കുന്നു"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index a9ef358..62a162e 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Томруулах"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Хандалтын ашиглалт"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Дэлгэц"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батарей ашиглаж байна"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батарей ашиглаж байна"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дэмжигч аппад нүүрэн талын үйлчилгээнүүдийг ардаас эхлүүлэхийг зөвшөөрнө."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофоныг ашиглах боломжгүй байна"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофоныг блоклосон байна"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Дэлгэцэд тусгал үүсгэх боломжгүй"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Өөр кабель ашиглаад, дахин оролдоно уу"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель нь дэлгэцүүдийг дэмждэггүй байж магадгүй"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Таны USB-C кабель дэлгэцүүдэд зохих ёсоор холбогдохгүй байж магадгүй"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen асаалттай байна"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> контент харуулахын тулд хоёр дэлгэцийг хоёуланг нь ашиглаж байна"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 485e9b6..87227ee 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अ‍ॅप्स"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"मॅग्निफिकेशन"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"अ‍ॅक्सेसिबिलिटी वापर"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"डिस्प्ले"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अ‍ॅप्स बॅटरी वापरत आहेत"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्‍या तपशीलांसाठी टॅप करा"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"सहयोगी अ‍ॅपला बॅकग्राउंडमधून फोरग्राउंड सेवा सुरू करण्याची अनुमती देते."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"मायक्रोफोन उपलब्ध आहे"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"मायक्रोफोन ब्लॉक केलेला आहे"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिस्प्लेवर मिरर करू शकत नाही"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"वेगळी केबल वापरून पुन्हा प्रयत्न करा"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"केबल कदाचित डिस्प्लेना सपोर्ट करणार नाही"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"तुमची USB-C केबल कदाचित डिस्प्लेना योग्यरीत्या कनेक्ट होणार नाही"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen सुरू आहे"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"आशय दाखवण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> दोन्ही डिस्प्ले वापरत आहे"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 3d3fc7c..7794150 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Penggunaan kebolehaksesan"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Paparan"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Benarkan apl rakan memulakan perkhidmatan latar depan dari latar."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon tersedia"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon disekat"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Tidak dapat menyegerakkan kepada paparan"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gunakan kabel lain dan cuba lagi"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel mungkin tidak menyokong paparan"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C anda mungkin tidak bersambung kepada paparan dengan betul"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dwiskrin"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dwiskrin dihidupkan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggunakan kedua-dua paparan untuk menunjukkan kandungan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 39dd043..3aaaf8b 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ချဲ့ခြင်း"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"အများသုံးစွဲနိုင်မှုကို အသုံးပြုမှု"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ဖန်သားပြင်"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"နောက်ခံမှနေ၍ မျက်နှာစာဝန်ဆောင်မှုများ စတင်ရန် တွဲဖက် အက်ပ်ကို ခွင့်ပြုသည်။"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"မိုက်ခရိုဖုန်း သုံးနိုင်သည်"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"မိုက်ခရိုဖုန်း ပိတ်ထားသည်"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ဖန်သားပြင်တွင် စကရင်ပွား၍ မရပါ"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"အခြားကေဘယ်ကြိုးသုံးပြီး ထပ်စမ်းကြည့်ပါ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ကေဘယ်ကြိုးက ဖန်သားပြင်များကို မပံ့ပိုးခြင်း ဖြစ်နိုင်သည်"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"သင့် USB-C ကေဘယ်ကြိုးသည် ဖန်သားပြင်များနှင့် မှန်ကန်စွာ ချိတ်ဆက်မထားခြင်း ဖြစ်နိုင်သည်"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ဖွင့်ထားသည်"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အကြောင်းအရာကို ပြရန် ဖန်သားပြင်နှစ်ခုစလုံးကို သုံးနေသည်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5b1f77c..9d6e805 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørring"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Bruk av Tilgjengelighet"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skjerm"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lar en følgeapp starte forgrunnstjenester fra bakgrunnen."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen er tilgjengelig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen er blokkert"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan ikke speile til skjermen"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Bruk en annen kabel og prøv igjen"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabelen støtter kanskje ikke skjermer"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C-kabelen din kobler seg kanskje ikke til skjermer på riktig måte"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen er på"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker begge skjermene til å vise innhold"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 603fad34..3b7de10 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"जुम इन गर्ने सुविधा"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"सर्वसुलभतासम्बन्धी सेवाहरूको प्रयोग"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"डिस्प्ले"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"यसले सहयोगी एपलाई ब्याकग्राउन्डमा फोरग्राउन्ड सेवाहरू चलाउने अनुमति दिन्छ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"माइक्रोफोन अनम्युट गरिएको छ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"माइक्रोफोन म्युट गरिएको छ"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिस्प्लेमा मिरर गर्न सकिएन"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"अर्कै केबल प्रयोग गरी फेरि प्रयास गर्नुहोस्"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"यो केबल डिस्प्लेहरूमा प्रयोग गर्न नमिल्न सक्छ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"तपाईंको USB-C केबल डिस्प्लेहरूमा राम्रोसँग नजोडिन सक्छ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen अन छ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले सामग्री देखाउन दुई वटै डिस्प्ले प्रयोग गरिरहेको छ"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 50e261f..ae7d366 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Toegankelijkheidsgebruik"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Scherm"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Hiermee kan een bijbehorende app services op de voorgrond vanuit de achtergrond starten."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfoon is beschikbaar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfoon is geblokkeerd"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan niet spiegelen naar scherm"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gebruik een andere kabel en probeer het opnieuw"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"De kabel ondersteunt misschien geen schermen"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Je USB-C-kabel sluit misschien niet goed aan op schermen"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen staat aan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt beide schermen om content te tonen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 52c9bf2..af76df8 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍‍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ମେଗ୍ନିଫିକେସନ"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ଆକ୍ସେସିବିଲିଟୀ ବ୍ୟବହାର"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ଡିସପ୍ଲେ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍‍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ପୃଷ୍ଠପଟରୁ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକ ଆରମ୍ଭ କରିବାକୁ ଏକ ସହଯୋଗୀ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ମାଇକ୍ରୋଫୋନ ଉପଲବ୍ଧ ଅଛି"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ଡିସପ୍ଲେ କରିବାକୁ ମିରର କରାଯାଇପାରିବ ନାହିଁ"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ଏକ ଭିନ୍ନ କେବୁଲ ବ୍ୟବହାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"କେବୁଲ ଡିସପ୍ଲେଗୁଡ଼ିକୁ ସମର୍ଥନ କରିନପାରେ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ଆପଣଙ୍କ USB-C କେବୁଲ ଡିସପ୍ଲେଗୁଡ଼ିକ ସହ ସଠିକ ଭାବରେ କନେକ୍ଟ ହୋଇନପାରେ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ଚାଲୁ ଅଛି"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ବିଷୟବସ୍ତୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଉଭୟ ଡିସପ୍ଲେକୁ ବ୍ୟବହାର କରୁଛି"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 8034be8..243e3e5 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ਪਹੁੰਚਯੋਗਤਾ ਵਰਤੋਂ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ਡਿਸਪਲੇ"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ਸੰਬੰਧੀ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਤੋਂ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਸ਼ੁਰੂ ਕਰਨ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਉਪਲਬਧ ਹੈ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ਡਿਸਪਲੇ \'ਤੇ ਪ੍ਰਤਿਬਿੰਬਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ਕੋਈ ਵੱਖਰੀ ਕੇਬਲ ਵਰਤ ਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੇਬਲ ਡਿਸਪਲੇਆਂ ਦਾ ਸਮਰਥਨ ਨਾ ਕਰੇ"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਤੁਹਾਡੀ USB-C ਕੇਬਲ ਡਿਸਪਲੇਆਂ ਨਾਲ ਠੀਕ ਤਰ੍ਹਾਂ ਕਨੈਕਟ ਨਾ ਹੋਵੇ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ਚਾਲੂ ਹੈ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਸਮੱਗਰੀ ਨੂੰ ਦਿਖਾਉਣ ਲਈ ਦੋਵੇਂ ਡਿਸਪਲੇਆਂ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b66ec02..18bea3f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Powiększenie"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Użycie ułatwień dostępu"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Wyświetlacz"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Zezwala aplikacji towarzyszącej na uruchamianie usług działających na pierwszym planie, podczas gdy sama działa w tle."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon jest dostępny"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon jest zablokowany"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nie można utworzyć odbicia lustrzanego na wyświetlaczu"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Użyj innego kabla i spróbuj ponownie"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel może nie obsługiwać wyświetlaczy"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C może nie łączyć się prawidłowo z wyświetlaczami"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Podwójny ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Włączono podwójny ekran"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> korzysta z obu wyświetlaczy, aby pokazać treści"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 628627d..486318d 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uso de acessibilidade"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Tela"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que um app complementar em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar a tela"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use outro cabo e tente de novo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Talvez o cabo não tenha suporte a telas"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Seu cabo USB-C pode não se conectar a telas corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tela dupla"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A tela dupla está ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está usando as duas telas para mostrar conteúdo"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c83491e..784f2a9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão a consumir bateria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Utilização da acessibilidade"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ecrã"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a consumir bateria."</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicações estão a consumir bateria."</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que uma app associada em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar para o ecrã"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use um cabo diferente e tente novamente"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"O cabo pode não suportar ecrãs"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"O cabo USB-C pode não se ligar a ecrãs corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Funcionalidade Dual Screen ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a usar ambos os ecrãs para mostrar conteúdo"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 628627d..486318d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uso de acessibilidade"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Tela"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que um app complementar em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar a tela"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use outro cabo e tente de novo"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Talvez o cabo não tenha suporte a telas"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Seu cabo USB-C pode não se conectar a telas corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tela dupla"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A tela dupla está ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está usando as duas telas para mostrar conteúdo"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 3389c63..88f5044 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Mărire"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Folosirea accesibilității"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ecran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atinge pentru mai multe detalii privind bateria și utilizarea datelor"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite unei aplicații partenere să inițieze servicii în prim-plan din fundal."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfonul este disponibil"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfonul este blocat"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nu se poate oglindi pe ecran"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Folosește alt cablu și încearcă din nou"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cablul poate să nu fie compatibil cu ecranele"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Cablul USB-C poate să nu se conecteze corespunzător la ecrane"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Funcția Dual screen este activată"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește ambele ecrane pentru a afișa conținut"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 920168a..7f5e87f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Сервисы специальных возможностей"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Экран"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Сопутствующее приложение сможет запускать активные службы из фонового режима."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон доступен."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон заблокирован."</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не удается дублировать на экран"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Используйте другой кабель или повторите попытку."</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель может не подходить для подключения к дисплеям"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Возможно, подключение дисплеев с помощью этого кабеля USB-C не поддерживается."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Функция Dual Screen включена"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> использует оба экрана."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 5f743a4..e90f1a2 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"විශාලනය"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ප්‍රවේශ්‍යතා භාවිතය"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"සංදර්ශකය"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"පසුබිමේ සිට පෙරබිම් සේවා ආරම්භ කිරීමට සහායක යෙදුමකට ඉඩ දෙයි."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"මයික්‍රෆෝනය තිබේ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"මයික්‍රෆෝනය අවහිර කර ඇත"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"සංදර්ශකයට දර්පණය කළ නොහැක"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"වෙනස් කේබලයක් භාවිතා කර නැවත උත්සාහ කරන්න"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"කේබලය සංදර්ශක වෙත සහාය නොදැක්විය හැක"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ඔබේ USB-C කේබලයට සංදර්ශකවලට නිසි ලෙස සම්බන්ධ නොවිය හැක"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen සක්‍රීයයි"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"අන්තර්ගතය පෙන්වීමට <xliff:g id="APP_NAME">%1$s</xliff:g> සංදර්ශන දෙකම භාවිත කරයි"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 6bbc110..3da576c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zväčšenie"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Využitie dostupnosti"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Obrazovka"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Umožňuje sprievodnej aplikácii spúšťať služby na popredí z pozadia."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofón je k dispozícii"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofón je blokovaný"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nedá sa zrkadliť do obrazovky"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Použite iný kábel a skúste znova"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kábel nemusí podporovať obrazovky"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kábel USB‑C sa nemusí dať správne pripojiť k obrazovkám"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Je zapnutá funkcia Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> zobrazuje obsah na oboch obrazovkách"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3999f9f..5b731b7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povečava"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Uporaba funkcij za dostopnost"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Zaslon"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Spremljevalni aplikaciji dovoljuje, da storitve v ospredju zažene iz ozadja."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je na voljo"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ni mogoče zrcaliti zaslona"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Uporabite drug kabel in poskusite znova"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel morda ne podpira zaslonov"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C se morda ne more ustrezno povezati z zasloni."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je vklopljen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> uporablja oba zaslona za prikaz vsebine."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index e746463..a4fd1bf1 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zmadhimi"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Përdorimi i qasshmërisë"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekrani"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lejon një aplikacion shoqërues të fillojë shërbimet në plan të parë nga sfondi."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoni ofrohet"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoni është i bllokuar"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nuk mund të pasqyrojë tek ekrani"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Përdor një kabllo tjetër dhe provo përsëri"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablloja nuk mund të mbështetë ekranet"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kablloja jote USB-C mund të mos lidhet siç duhet me ekranet"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen është aktiv"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> po i përdor të dyja ekranet për të shfaqur përmbajtje"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b5aefaa..e5ae2f7 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -291,6 +291,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увећање"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Коришћење Приступачности"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Екран"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string>
@@ -314,7 +315,7 @@
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Музика и звук"</string>
     <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"приступ музици и аудио садржају на уређају"</string>
     <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Слике и видео снимци"</string>
-    <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"приступ сликама и видео снимцима на уређају"</string>
+    <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"приступ сликама и видеима на уређају"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"снима звук"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Физичке активности"</string>
@@ -2334,6 +2335,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозвољава пратећој апликацији да покрене услуге у првом плану из позадине."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон је доступан"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон је блокиран"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Пресликавање на екран није могуће"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Употребите други кабл и пробајте поново"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабл не подржава екране"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабл се не повезује правилно са екранима"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen је укључен"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи оба екрана за приказивање садржаја"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index a24ca19..f3917fe 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Förstoring"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Tillgänglighetsanvändning"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skärm"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tillåter att en tillhörande app startar förgrundstjänster i bakgrunden."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen är tillgänglig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen är blockerad"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Det går inte spegla till skärmen"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Använd en annan kabel och försök igen"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabeln kanske inte har stöd för skärmar"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Det kanske inte går att ansluta skärmar korrekt med den här USB-C-kabeln"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen är på"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> använder båda skärmarna för att visa innehåll"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 7171486..95c1b25 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukuzaji"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Matumizi ya zana za ufikivu"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Skrini"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Huruhusu programu oanifu kuanzisha huduma zinazoonekana kwenye skrini kutoka katika huduma zinazoendelea chinichini."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Maikrofoni inapatikana"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Maikrofoni imezuiwa"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Imeshindwa kuakisi kwenye skrini"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Tumia kebo tofauti kisha ujaribu tena"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Huenda kebo haioani na skrini"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Huenda kebo yako ya USB-C isiunganishwe vizuri na skrini"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen imewasha"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia skrini zote kuonyesha maudhui"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 4fe363e..9ad4bd2 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"பெரிதாக்கல்"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"அணுகல்தன்மை உபயோகம்"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"டிஸ்ப்ளே"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"பின்னணியிலிருந்து முன்புலச் சேவைகளைத் தொடங்க துணைத் தயாரிப்பு ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"மைக்ரோஃபோன் இயக்கப்பட்டது"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"மைக்ரோஃபோன் முடக்கப்பட்டுள்ளது"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"டிஸ்ப்ளேயில் பிரதிபலிக்க முடியவில்லை"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"வெவ்வேறு கேபிள்களைப் பயன்படுத்தி மீண்டும் முயலவும்"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"டிஸ்ப்ளேக்களைக் கேபிள் ஆதரிக்காமல் இருக்கக்கூடும்"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"டிஸ்ப்ளேக்களில் உங்கள் USB-C கேபிள் சரியாக இணைக்கப்படாமல் இருக்கக்கூடும்"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"இரட்டைத் திரை"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"இரட்டைத் திரை அம்சம் இயக்கத்தில் உள்ளது"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"உள்ளடக்கத்தைக் காட்டுவதற்கு இரண்டு டிஸ்ப்ளேக்களையும் <xliff:g id="APP_NAME">%1$s</xliff:g> பயன்படுத்துகிறது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index aa22aea..d1c336d 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్‌లు"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మ్యాగ్నిఫికేషన్"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"యాక్సెసిబిలిటీ వినియోగం"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"డిస్‌ప్లే చేయండి"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్‌లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"బ్యాక్‌గ్రౌండ్ నుండి ఫోర్‌గ్రౌండ్ సర్వీస్‌లను ప్రారంభించడానికి సహాయక యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"మైక్రోఫోన్ అందుబాటులో ఉంది"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"మైక్రోఫోన్ బ్లాక్ చేయబడింది"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"డిస్‌ప్లే చేయడానికి మిర్రర్ చేయడం సాధ్యపడదు"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"వేరే కేబుల్‌ను ఉపయోగించి, మళ్లీ ట్రై చేయండి"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"డిస్‌ప్లేలను కేబుల్ సపోర్ట్ చేయకపోవచ్చు"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"మీ USB-C కేబుల్, డిస్‌ప్లేలకు సరిగ్గా కనెక్ట్ కాకపోవచ్చు"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ఆన్‌లో ఉంది"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"కంటెంట్‌ను చూపడం కోసం <xliff:g id="APP_NAME">%1$s</xliff:g> రెండు డిస్‌ప్లేలనూ ఉపయోగిస్తోంది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index eb4e2f7..4f53fcd 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"การขยาย"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"การใช้งานการช่วยเหลือพิเศษ"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"จอแสดงผล"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"อนุญาตจากเบื้องหลังให้แอปที่ใช้ร่วมกันเริ่มการทำงานของบริการที่ทำงานอยู่เบื้องหน้า"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ไมโครโฟนพร้อมใช้งาน"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ไมโครโฟนถูกบล็อก"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"มิเรอร์ไปยังจอแสดงผลไม่ได้"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"โปรดใช้สายอื่นและลองอีกครั้ง"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"สายสัญญาณอาจไม่รองรับจอแสดงผล"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"สาย USB-C อาจเชื่อมต่อกับจอแสดงผลอย่างไม่ถูกต้อง"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen เปิดอยู่"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้จอแสดงผลทั้งสองจอเพื่อแสดงเนื้อหา"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7249c51..2477698 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pag-magnify"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Paggamit sa pagiging accessible"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Display"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Nagbibigay-daan sa kasamang app na magsimula ng mga serbisyo sa foreground mula sa background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Available ang mikropono"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Naka-block ang mikropono"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Hindi makapag-mirror sa display"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gumamit ng ibang cable at subukan ulit"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Posibleng hindi sinusuportahan ng cable ang mga display"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Posibleng hindi kumonekta nang maayos sa mga display ang iyong USB-C cable"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Naka-on ang dual screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Ginagamit ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang parehong display para magpakita ng content"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8f02efd..2ebfe91 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Büyütme"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Erişilebilirlik kullanımı"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Ekran"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tamamlayıcı uygulamanın arka plandan ön plan hizmetlerini başlatmasına izin verir."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon kullanılabilir"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon engellenmiş"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ekrana yansıtılamıyor"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Farklı kablo kullanarak tekrar deneyin"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablo, ekranları desteklemeyebilir"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kablonuz ekranlara doğru şekilde bağlanamayabilir"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen açık"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>, içeriği göstermek için her iki ekranı da kullanıyor"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d34e976..d4cd207 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -292,6 +292,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Збільшення"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Використання спеціальних можливостей"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Дисплей"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string>
@@ -2335,6 +2336,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозволяє супутньому додатку запускати активні сервіси у фоновому режимі."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Мікрофон доступний"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Мікрофон заблоковано"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Неможливо дублювати на дисплей"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Скористайтесь іншим кабелем і повторіть спробу"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель може не підтримувати дисплеї"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ваш кабель USB-C може не підключатися до дисплеїв належним чином"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen увімкнено"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує обидва екрани для показу контенту"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 631a573..8634294 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"میگنیفکیشن"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"ایکسیسبیلٹی کا استعمال"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"ڈسپلے"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ساتھی ایپ کو پس منظر سے پیش منظر کی سروسز شروع کرنے کی اجازت دیتی ہے۔"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"مائیکروفون دستیاب ہے"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"مائیکروفون مسدود ہے"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ڈسپلے پر دو طرفہ مطابقت پذیری ممکن نہیں ہے"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"مختلف کیبل استعمال کریں اور دوبارہ کوشش کریں"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ہو سکتا ہے کہ کیبل ڈسپلیز کو سپورٹ نہ کرے"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏ہو سکتا ہے کہ آپ کی USB-C کیبل مناسب طریقے سے ڈسپلیز سے منسلک نہ ہو"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"دوہری اسکرین"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"دوہری اسکرین آن ہے"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"مواد دکھانے کیلئے <xliff:g id="APP_NAME">%1$s</xliff:g> دونوں ڈسپلیز استعمال کر رہی ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 4262342..fdea194 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Kattalashtirish"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Qulayliklar ishlatilishi"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Displey"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Hamroh ilovaga faol xizmatlarni fonda ishga tushirishga ruxsat beradi."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon yoqildi"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon bloklandi"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Displeyga translatsiya qilinmaydi"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Boshqa kabel yordamida qayta urining"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel displeylar bilan ishlamasligi mumkin"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabelingiz displeylarga toʻgʻri ulanmasligi mumkin"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Ikkita ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Ikki ekranli rejim yoniq"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> kontentni ikkala ekranda chiqarmoqda"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 78318b1..12a61ed 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Phóng to"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Việc sử dụng tính năng hỗ trợ tiếp cận"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Màn hình"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Cho phép một ứng dụng đồng hành bắt đầu các dịch vụ trên nền trước từ nền."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Micrô đang hoạt động"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Micrô đang bị chặn"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Không chiếu được nội dung lên màn hình"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Hãy dùng một cáp khác rồi thử lại"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Có thể cáp không hỗ trợ màn hình"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Có thể cáp USB-C của bạn chưa kết nối đúng cách với màn hình"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Chế độ Dual screen bật"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang dùng cả hai màn hình để thể hiện nội dung"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 16c1013..d79a772 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大功能"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"无障碍功能使用情况"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"显示屏"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允许配套应用从后台启动前台服务。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"麦克风可用"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"麦克风已被屏蔽"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"无法镜像到显示屏"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"请改用其他数据线并重试"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"数据线可能不支持显示屏"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"您的 USB-C 数据线可能没有正确连接到显示屏"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"双屏幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"双屏幕功能已开启"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在使用双屏幕显示内容"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 06ec1dd..fe3644e 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"無障礙功能使用情況"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"顯示屏"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允許隨附應用程式從背景啟動前景服務。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"可以使用麥克風"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"已封鎖麥克風"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"無法將畫面鏡像投放至螢幕"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"請改用其他連接線,然後再試一次"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"連接線可能不支援顯示屏"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"你的 USB-C 連接線可能未妥善連接顯示屏"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"已開啟雙螢幕功能"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 81bdc37..5b65201 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"無障礙功能使用情形"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"螢幕"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允許隨附應用程式從背景啟動前景服務。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"麥克風已可使用"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"麥克風已封鎖"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"無法將畫面鏡像投放至螢幕"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"請改用其他傳輸線,然後再試一次"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"傳輸線可能不支援螢幕"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C 傳輸線可能未妥善連接到螢幕"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"雙螢幕功能已啟用"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a2eb545..b701abe 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -290,6 +290,7 @@
     <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukukhuliswa"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"Ukusetshenziswa kokufinyeleleka"</string>
+    <string name="notification_channel_display" msgid="6905032605735615090">"Bonisa"</string>
     <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string>
     <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string>
     <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string>
@@ -2333,6 +2334,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ivumela i-app ehambisanayo ukuthi iqale amasevisi angaphambili kusukela ngemuva."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Imakrofoni iyatholakala"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Imakrofoni ivinjiwe"</string>
+    <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ayikwazi ukufanisa nesibonisi"</string>
+    <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Sebenzisa ikhebuli ehlukile bese uyazama futhi"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Ikhebuli ingase ingasekeli iziboniso"</string>
+    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ikhebuli yakho ye-USB-C ingase ingaxhumi kahle kuzibonisi"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Isikrini esikabili"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Isikrini esikabili sivuliwe"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa zombili izibonisi ukukhombisa okuqukethwe"</string>
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
index 531404b..d10cf16 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
@@ -62,4 +62,24 @@
         verify(callback2, times(1)).preExecute(clientTransactionHandler);
         verify(stateRequest, times(1)).preExecute(clientTransactionHandler);
     }
+
+    @Test
+    public void testPreExecuteTransactionItems() {
+        final ClientTransactionItem callback1 = mock(ClientTransactionItem.class);
+        final ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
+        final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
+        final ClientTransactionHandler clientTransactionHandler =
+                mock(ClientTransactionHandler.class);
+
+        final ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        transaction.addTransactionItem(callback1);
+        transaction.addTransactionItem(callback2);
+        transaction.addTransactionItem(stateRequest);
+
+        transaction.preExecute(clientTransactionHandler);
+
+        verify(callback1, times(1)).preExecute(clientTransactionHandler);
+        verify(callback2, times(1)).preExecute(clientTransactionHandler);
+        verify(stateRequest, times(1)).preExecute(clientTransactionHandler);
+    }
 }
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 44a4d58..f2b0f2e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -247,6 +247,31 @@
     }
 
     @Test
+    public void testExecuteTransactionItems_transactionResolution() {
+        ClientTransactionItem callback1 = mock(ClientTransactionItem.class);
+        when(callback1.getPostExecutionState()).thenReturn(UNDEFINED);
+        ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
+        when(callback2.getPostExecutionState()).thenReturn(UNDEFINED);
+        ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
+        IBinder token = mock(IBinder.class);
+        when(stateRequest.getActivityToken()).thenReturn(token);
+        when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
+
+        ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        transaction.addTransactionItem(callback1);
+        transaction.addTransactionItem(callback2);
+        transaction.addTransactionItem(stateRequest);
+
+        transaction.preExecute(mTransactionHandler);
+        mExecutor.execute(transaction);
+
+        InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2, stateRequest);
+        inOrder.verify(callback1).execute(eq(mTransactionHandler), any());
+        inOrder.verify(callback2).execute(eq(mTransactionHandler), any());
+        inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+    }
+
+    @Test
     public void testDoNotLaunchDestroyedActivity() {
         final Map<IBinder, DestroyActivityItem> activitiesToBeDestroyed = new ArrayMap<>();
         when(mTransactionHandler.getActivitiesToBeDestroyed()).thenReturn(activitiesToBeDestroyed);
@@ -279,12 +304,43 @@
     }
 
     @Test
+    public void testExecuteTransactionItems_doNotLaunchDestroyedActivity() {
+        final Map<IBinder, DestroyActivityItem> activitiesToBeDestroyed = new ArrayMap<>();
+        when(mTransactionHandler.getActivitiesToBeDestroyed()).thenReturn(activitiesToBeDestroyed);
+        // Assume launch transaction is still in queue, so there is no client record.
+        when(mTransactionHandler.getActivityClient(any())).thenReturn(null);
+
+        // An incoming destroy transaction enters binder thread (preExecute).
+        final IBinder token = mock(IBinder.class);
+        final ClientTransaction destroyTransaction = ClientTransaction.obtain(null /* client */);
+        destroyTransaction.addTransactionItem(
+                DestroyActivityItem.obtain(token, false /* finished */, 0 /* configChanges */));
+        destroyTransaction.preExecute(mTransactionHandler);
+        // The activity should be added to to-be-destroyed container.
+        assertEquals(1, activitiesToBeDestroyed.size());
+
+        // A previous queued launch transaction runs on main thread (execute).
+        final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */);
+        final LaunchActivityItem launchItem =
+                spy(new LaunchActivityItemBuilder().setActivityToken(token).build());
+        launchTransaction.addTransactionItem(launchItem);
+        mExecutor.execute(launchTransaction);
+
+        // The launch transaction should not be executed because its token is in the
+        // to-be-destroyed container.
+        verify(launchItem, never()).execute(any(), any());
+
+        // After the destroy transaction has been executed, the token should be removed.
+        mExecutor.execute(destroyTransaction);
+        assertTrue(activitiesToBeDestroyed.isEmpty());
+    }
+
+    @Test
     public void testActivityResultRequiredStateResolution() {
         when(mTransactionHandler.getActivity(any())).thenReturn(mock(Activity.class));
 
         PostExecItem postExecItem = new PostExecItem(ON_RESUME);
 
-        IBinder token = mock(IBinder.class);
         ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
         transaction.addCallback(postExecItem);
 
@@ -300,6 +356,26 @@
     }
 
     @Test
+    public void testExecuteTransactionItems_activityResultRequiredStateResolution() {
+        when(mTransactionHandler.getActivity(any())).thenReturn(mock(Activity.class));
+
+        PostExecItem postExecItem = new PostExecItem(ON_RESUME);
+
+        ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        transaction.addTransactionItem(postExecItem);
+
+        // Verify resolution that should get to onPause
+        mClientRecord.setState(ON_RESUME);
+        mExecutor.executeTransactionItems(transaction);
+        verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction));
+
+        // Verify resolution that should get to onStart
+        mClientRecord.setState(ON_STOP);
+        mExecutor.executeTransactionItems(transaction);
+        verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction));
+    }
+
+    @Test
     public void testClosestStateResolutionForSameState() {
         final int[] allStates = new int[] {
                 ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY};
@@ -444,6 +520,18 @@
         mExecutor.executeCallbacks(transaction);
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testExecuteTransactionItems_activityItemNullRecordThrowsException() {
+        final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
+        when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
+        final IBinder token = mock(IBinder.class);
+        final ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        transaction.addTransactionItem(activityItem);
+        when(mTransactionHandler.getActivityClient(token)).thenReturn(null);
+
+        mExecutor.executeTransactionItems(transaction);
+    }
+
     @Test
     public void testActivityItemExecute() {
         final IBinder token = mock(IBinder.class);
@@ -464,6 +552,26 @@
         inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
     }
 
+    @Test
+    public void testExecuteTransactionItems_activityItemExecute() {
+        final IBinder token = mock(IBinder.class);
+        final ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
+        when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
+        when(activityItem.getActivityToken()).thenReturn(token);
+        transaction.addTransactionItem(activityItem);
+        final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
+        transaction.addTransactionItem(stateRequest);
+        when(stateRequest.getActivityToken()).thenReturn(token);
+        when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
+
+        mExecutor.execute(transaction);
+
+        final InOrder inOrder = inOrder(activityItem, stateRequest);
+        inOrder.verify(activityItem).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+        inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+    }
+
     private static int[] shuffledArray(int[] inputArray) {
         final List<Integer> list = Arrays.stream(inputArray).boxed().collect(Collectors.toList());
         Collections.shuffle(list);
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 7d047c9..4aa62c5 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -285,6 +285,10 @@
                 78 /* configChanges */);
 
         ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
+        transaction.addTransactionItem(callback1);
+        transaction.addTransactionItem(callback2);
+        transaction.addTransactionItem(lifecycleRequest);
+
         transaction.addCallback(callback1);
         transaction.addCallback(callback2);
         transaction.setLifecycleStateRequest(lifecycleRequest);
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 3f78396..0d687b2 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import static com.android.text.flags.Flags.FLAG_CUSTOM_LOCALE_FALLBACK;
+import static com.android.text.flags.Flags.FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -931,7 +931,7 @@
         return String.format(xml, op, lang, font);
     }
 
-    @RequiresFlagsEnabled(FLAG_CUSTOM_LOCALE_FALLBACK)
+    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_prepend() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -947,7 +947,7 @@
         assertB3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_CUSTOM_LOCALE_FALLBACK)
+    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_replace() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -963,7 +963,7 @@
         assertB3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_CUSTOM_LOCALE_FALLBACK)
+    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_append() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -979,7 +979,7 @@
         assertA3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_CUSTOM_LOCALE_FALLBACK)
+    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_ScriptMismatch() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -995,7 +995,7 @@
         assertA3emFontIsUsed(typeface);
     }
 
-    @RequiresFlagsEnabled(FLAG_CUSTOM_LOCALE_FALLBACK)
+    @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
     @Test
     public void testBuildSystemFallback__Customization_locale_SubscriptMatch() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
diff --git a/core/tests/coretests/src/android/view/ScrollFeedbackProviderTest.java b/core/tests/coretests/src/android/view/ScrollFeedbackProviderTest.java
new file mode 100644
index 0000000..6acab36
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ScrollFeedbackProviderTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public final class ScrollFeedbackProviderTest {
+    private final Context mContext = InstrumentationRegistry.getContext();
+
+    @Test
+    public void testDefaultProviderType() {
+        View view = new View(mContext);
+
+        ScrollFeedbackProvider provider = ScrollFeedbackProvider.createProvider(view);
+
+        assertThat(provider).isInstanceOf(HapticScrollFeedbackProvider.class);
+    }
+
+    @Test
+    public void testDefaultProvider_createsDistinctProvidesOnMultipleCalls() {
+        View view1 = new View(mContext);
+        View view2 = new View(mContext);
+
+        ScrollFeedbackProvider view1Provider1 = ScrollFeedbackProvider.createProvider(view1);
+        ScrollFeedbackProvider view1Provider2 = ScrollFeedbackProvider.createProvider(view1);
+        ScrollFeedbackProvider view2Provider = ScrollFeedbackProvider.createProvider(view2);
+
+        assertThat(view1Provider1 == view1Provider2).isFalse();
+        assertThat(view1Provider1 == view2Provider).isFalse();
+    }
+}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9fde0fd..4eaa013 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2113,6 +2113,31 @@
          * The recommended additional space to add between lines of text.
          */
         public float   leading;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || !(o instanceof FontMetrics)) return false;
+            FontMetrics that = (FontMetrics) o;
+            return that.top == top && that.ascent == ascent && that.descent == descent
+                    && that.bottom == bottom && that.leading == leading;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(top, ascent, descent, bottom, leading);
+        }
+
+        @Override
+        public String toString() {
+            return "FontMetrics{"
+                    + "top=" + top
+                    + ", ascent=" + ascent
+                    + ", descent=" + descent
+                    + ", bottom=" + bottom
+                    + ", leading=" + leading
+                    + '}';
+        }
     }
 
     /**
@@ -2309,6 +2334,33 @@
          */
         public int   leading;
 
+        /**
+         * Set values from {@link FontMetricsInt}.
+         * @param fontMetricsInt a font metrics.
+         */
+        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+        public void set(@NonNull FontMetricsInt fontMetricsInt) {
+            top = fontMetricsInt.top;
+            ascent = fontMetricsInt.ascent;
+            descent = fontMetricsInt.descent;
+            bottom = fontMetricsInt.bottom;
+            leading = fontMetricsInt.leading;
+        }
+
+        /**
+         * Set values from {@link FontMetrics} with rounding accordingly.
+         * @param fontMetrics a font metrics.
+         */
+        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
+        public void set(@NonNull FontMetrics fontMetrics) {
+            // See GraphicsJNI::set_metrics_int method for consistency.
+            top = (int) Math.floor(fontMetrics.top);
+            ascent = Math.round(fontMetrics.ascent);
+            descent = Math.round(fontMetrics.descent);
+            bottom = (int) Math.ceil(fontMetrics.bottom);
+            leading = Math.round(fontMetrics.leading);
+        }
+
         @Override public String toString() {
             return "FontMetricsInt: top=" + top + " ascent=" + ascent +
                     " descent=" + descent + " bottom=" + bottom +
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index 6e04a2f..ba5628c 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -182,7 +182,7 @@
 
             // For ignoring the customization, consume the new-locale-family element but don't
             // register any customizations.
-            if (com.android.text.flags.Flags.customLocaleFallback()) {
+            if (com.android.text.flags.Flags.vendorCustomLocaleFallback()) {
                 outCustomization.add(new FontConfig.Customization.LocaleFallback(
                         Locale.forLanguageTag(lang), intOp, family));
             }
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 4c75356..685fd82 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -16,7 +16,7 @@
 
 package android.graphics.fonts;
 
-import static com.android.text.flags.Flags.FLAG_DEPRECATE_FONTS_XML;
+import static com.android.text.flags.Flags.FLAG_NEW_FONTS_FALLBACK_XML;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -145,7 +145,7 @@
          * @return A variable font family. null if a variable font cannot be built from the given
          *         fonts.
          */
-        @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+        @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
         public @Nullable FontFamily buildVariableFamily() {
             int variableFamilyType = analyzeAndResolveVariableType(mFonts);
             if (variableFamilyType == VARIABLE_FONT_FAMILY_TYPE_UNKNOWN) {
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 618aa5b..3ef714ed 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -241,7 +241,7 @@
             int configVersion
     ) {
         final String fontsXml;
-        if (com.android.text.flags.Flags.deprecateFontsXml()) {
+        if (com.android.text.flags.Flags.newFontsFallbackXml()) {
             fontsXml = FONTS_XML;
         } else {
             fontsXml = LEGACY_FONTS_XML;
@@ -272,7 +272,7 @@
      */
     public static @NonNull FontConfig getSystemPreinstalledFontConfig() {
         final String fontsXml;
-        if (com.android.text.flags.Flags.deprecateFontsXml()) {
+        if (com.android.text.flags.Flags.newFontsFallbackXml()) {
             fontsXml = FONTS_XML;
         } else {
             fontsXml = LEGACY_FONTS_XML;
diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java
index 569f9b6..7932e33 100644
--- a/graphics/java/android/graphics/text/PositionedGlyphs.java
+++ b/graphics/java/android/graphics/text/PositionedGlyphs.java
@@ -16,7 +16,7 @@
 
 package android.graphics.text;
 
-import static com.android.text.flags.Flags.FLAG_DEPRECATE_FONTS_XML;
+import static com.android.text.flags.Flags.FLAG_NEW_FONTS_FALLBACK_XML;
 
 import android.annotation.FlaggedApi;
 import android.annotation.IntRange;
@@ -173,7 +173,7 @@
      * @param index the glyph index
      * @return true if the fake bold option is on, otherwise off.
      */
-    @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+    @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
     public boolean getFakeBold(@IntRange(from = 0) int index) {
         Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index");
         return nGetFakeBold(mLayoutPtr, index);
@@ -185,7 +185,7 @@
      * @param index the glyph index
      * @return true if the fake italic option is on, otherwise off.
      */
-    @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+    @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
     public boolean getFakeItalic(@IntRange(from = 0) int index) {
         Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index");
         return nGetFakeItalic(mLayoutPtr, index);
@@ -195,7 +195,7 @@
      * A special value returned by {@link #getWeightOverride(int)} and
      * {@link #getItalicOverride(int)} that indicates no font variation setting is overridden.
      */
-    @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+    @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
     public static final float NO_OVERRIDE = Float.MIN_VALUE;
 
     /**
@@ -205,7 +205,7 @@
      * @param index the glyph index
      * @return overridden weight value or {@link #NO_OVERRIDE}.
      */
-    @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+    @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
     public float getWeightOverride(@IntRange(from = 0) int index) {
         Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index");
         float value = nGetWeightOverride(mLayoutPtr, index);
@@ -223,7 +223,7 @@
      * @param index the glyph index
      * @return overridden weight value or {@link #NO_OVERRIDE}.
      */
-    @FlaggedApi(FLAG_DEPRECATE_FONTS_XML)
+    @FlaggedApi(FLAG_NEW_FONTS_FALLBACK_XML)
     public float getItalicOverride(@IntRange(from = 0) int index) {
         Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index");
         float value = nGetItalicOverride(mLayoutPtr, index);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/OverlayCreateParams.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/OverlayCreateParams.java
new file mode 100644
index 0000000..ff49cdc
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/OverlayCreateParams.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static java.util.Objects.requireNonNull;
+
+import android.graphics.Rect;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * The parameter to create an overlay container that retrieved from
+ * {@link android.app.ActivityOptions} bundle.
+ */
+class OverlayCreateParams {
+
+    // TODO(b/295803704): Move them to WM Extensions so that we can reuse in WM Jetpack.
+    @VisibleForTesting
+    static final String KEY_OVERLAY_CREATE_PARAMS =
+            "androidx.window.extensions.OverlayCreateParams";
+
+    @VisibleForTesting
+    static final String KEY_OVERLAY_CREATE_PARAMS_TASK_ID =
+            "androidx.window.extensions.OverlayCreateParams.taskId";
+
+    @VisibleForTesting
+    static final String KEY_OVERLAY_CREATE_PARAMS_TAG =
+            "androidx.window.extensions.OverlayCreateParams.tag";
+
+    @VisibleForTesting
+    static final String KEY_OVERLAY_CREATE_PARAMS_BOUNDS =
+            "androidx.window.extensions.OverlayCreateParams.bounds";
+
+    private final int mTaskId;
+
+    @NonNull
+    private final String mTag;
+
+    @NonNull
+    private final Rect mBounds;
+
+    OverlayCreateParams(int taskId, @NonNull String tag, @NonNull Rect bounds) {
+        mTaskId = taskId;
+        mTag = requireNonNull(tag);
+        mBounds = requireNonNull(bounds);
+    }
+
+    int getTaskId() {
+        return mTaskId;
+    }
+
+    @NonNull
+    String getTag() {
+        return mTag;
+    }
+
+    @NonNull
+    Rect getBounds() {
+        return mBounds;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mTaskId;
+        result = 31 * result + mTag.hashCode();
+        result = 31 * result + mBounds.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (!(obj instanceof OverlayCreateParams thatParams)) return false;
+        return mTaskId == thatParams.mTaskId
+                && mTag.equals(thatParams.mTag)
+                && mBounds.equals(thatParams.mBounds);
+    }
+
+    @Override
+    public String toString() {
+        return OverlayCreateParams.class.getSimpleName() + ": {"
+                + "taskId=" + mTaskId
+                + ", tag=" + mTag
+                + ", bounds=" + mBounds
+                + "}";
+    }
+
+    /** Retrieves the {@link OverlayCreateParams} from {@link android.app.ActivityOptions} bundle */
+    @Nullable
+    static OverlayCreateParams fromBundle(@NonNull Bundle bundle) {
+        final Bundle paramsBundle = bundle.getBundle(KEY_OVERLAY_CREATE_PARAMS);
+        if (paramsBundle == null) {
+            return null;
+        }
+        final int taskId = paramsBundle.getInt(KEY_OVERLAY_CREATE_PARAMS_TASK_ID);
+        final String tag = requireNonNull(paramsBundle.getString(KEY_OVERLAY_CREATE_PARAMS_TAG));
+        final Rect bounds = requireNonNull(paramsBundle.getParcelable(
+                KEY_OVERLAY_CREATE_PARAMS_BOUNDS, Rect.class));
+
+        return new OverlayCreateParams(taskId, tag, bounds);
+    }
+}
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 cdfc4c8..49606f0 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -40,9 +40,10 @@
 import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenAdjacent;
 import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
 import static androidx.window.extensions.embedding.SplitPresenter.RESULT_EXPAND_FAILED_NO_TF_INFO;
+import static androidx.window.extensions.embedding.SplitPresenter.boundsSmallerThanMinDimensions;
 import static androidx.window.extensions.embedding.SplitPresenter.getActivitiesMinDimensionsPair;
 import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
-import static androidx.window.extensions.embedding.SplitPresenter.getTaskWindowMetrics;
+import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
 import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSplit;
 
 import android.app.Activity;
@@ -87,6 +88,7 @@
 import androidx.window.extensions.layout.WindowLayoutComponentImpl;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -123,8 +125,7 @@
      * and unregistered via {@link #clearSplitAttributesCalculator()}.
      * This is called when:
      * <ul>
-     *   <li>{@link SplitPresenter#updateSplitContainer(SplitContainer, TaskFragmentContainer,
-     *     WindowContainerTransaction)}</li>
+     *   <li>{@link SplitPresenter#updateSplitContainer}</li>
      *   <li>There's a started Activity which matches {@link SplitPairRule} </li>
      *   <li>Checking whether the place holder should be launched if there's a Activity matches
      *   {@link SplitPlaceholderRule} </li>
@@ -291,8 +292,8 @@
             // Resets the isolated navigation and updates the container.
             final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
             final WindowContainerTransaction wct = transactionRecord.getTransaction();
-            mPresenter.setTaskFragmentIsolatedNavigation(wct,
-                    containerToUnpin.getTaskFragmentToken(), false /* isolated */);
+            mPresenter.setTaskFragmentIsolatedNavigation(wct, containerToUnpin,
+                    false /* isolated */);
             updateContainer(wct, containerToUnpin);
             transactionRecord.apply(false /* shouldApplyIndependently */);
             updateCallbackIfNecessary();
@@ -759,6 +760,8 @@
         if (targetContainer == null) {
             // When there is no embedding rule matched, try to place it in the top container
             // like a normal launch.
+            // TODO(b/301034784): Check if it makes sense to place the activity in overlay
+            //  container.
             targetContainer = taskContainer.getTopNonFinishingTaskFragmentContainer();
         }
         if (targetContainer == null) {
@@ -877,19 +880,17 @@
             return true;
         }
 
-        // Skip resolving if the activity is on a pinned TaskFragmentContainer.
-        // TODO(b/243518738): skip resolving for overlay container.
-        final TaskContainer taskContainer = container != null ? container.getTaskContainer() : null;
-        if (container != null && taskContainer != null
-                && taskContainer.isTaskFragmentContainerPinned(container)) {
+        // Skip resolving if the activity is on an isolated navigated TaskFragmentContainer.
+        if (container != null && container.isIsolatedNavigationEnabled()) {
             return true;
         }
 
+        final TaskContainer taskContainer = container != null ? container.getTaskContainer() : null;
         if (!isOnReparent && taskContainer != null
                 && taskContainer.getTopNonFinishingTaskFragmentContainer(false /* includePin */)
                         != container) {
             // Do not resolve if the launched activity is not the top-most container (excludes
-            // the pinned container) in the Task.
+            // the pinned and overlay container) in the Task.
             return true;
         }
 
@@ -1007,6 +1008,7 @@
         if (taskContainer == null) {
             return;
         }
+        // TODO(b/301034784): Check if it makes sense to place the activity in overlay container.
         final TaskFragmentContainer targetContainer =
                 taskContainer.getTopNonFinishingTaskFragmentContainer();
         if (targetContainer == null) {
@@ -1166,7 +1168,7 @@
                 getActivitiesMinDimensionsPair(primaryActivity, secondaryActivity));
         if (splitContainer != null && primaryContainer == splitContainer.getPrimaryContainer()
                 && canReuseContainer(splitRule, splitContainer.getSplitRule(),
-                        getTaskWindowMetrics(taskProperties.getConfiguration()),
+                        taskProperties.getTaskMetrics(),
                         calculatedSplitAttributes, splitContainer.getCurrentSplitAttributes())) {
             // Can launch in the existing secondary container if the rules share the same
             // presentation.
@@ -1308,15 +1310,12 @@
     @GuardedBy("mLock")
     TaskFragmentContainer resolveStartActivityIntent(@NonNull WindowContainerTransaction wct,
             int taskId, @NonNull Intent intent, @Nullable Activity launchingActivity) {
-        // Skip resolving if started from pinned TaskFragmentContainer.
-        // TODO(b/243518738): skip resolving for overlay container.
+        // Skip resolving if started from an isolated navigated TaskFragmentContainer.
         if (launchingActivity != null) {
             final TaskFragmentContainer taskFragmentContainer = getContainerWithActivity(
                     launchingActivity);
-            final TaskContainer taskContainer =
-                    taskFragmentContainer != null ? taskFragmentContainer.getTaskContainer() : null;
-            if (taskContainer != null && taskContainer.isTaskFragmentContainerPinned(
-                    taskFragmentContainer)) {
+            if (taskFragmentContainer != null
+                    && taskFragmentContainer.isIsolatedNavigationEnabled()) {
                 return null;
             }
         }
@@ -1408,6 +1407,22 @@
     private TaskFragmentContainer createEmptyExpandedContainer(
             @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
             @Nullable Activity launchingActivity) {
+        return createEmptyContainer(wct, intent, taskId, new Rect(), launchingActivity,
+                null /* overlayTag */);
+    }
+
+    /**
+     * Returns an empty {@link TaskFragmentContainer} that we can launch an activity into.
+     * If {@code overlayTag} is set, it means the created {@link TaskFragmentContainer} is an
+     * overlay container.
+     */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    @Nullable
+    TaskFragmentContainer createEmptyContainer(
+            @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
+            @NonNull Rect bounds, @Nullable Activity launchingActivity,
+            @Nullable String overlayTag) {
         // We need an activity in the organizer process in the same Task to use as the owner
         // activity, as well as to get the Task window info.
         final Activity activityInTask;
@@ -1423,13 +1438,46 @@
             // Can't find any activity in the Task that we can use as the owner activity.
             return null;
         }
-        final TaskFragmentContainer expandedContainer = newContainer(intent, activityInTask,
-                taskId);
-        mPresenter.createTaskFragment(wct, expandedContainer.getTaskFragmentToken(),
-                activityInTask.getActivityToken(), new Rect(), WINDOWING_MODE_UNDEFINED);
-        mPresenter.updateAnimationParams(wct, expandedContainer.getTaskFragmentToken(),
+        final TaskFragmentContainer container = newContainer(null /* pendingAppearedActivity */,
+                intent, activityInTask, taskId, null /* pairedPrimaryContainer*/, overlayTag);
+        final IBinder taskFragmentToken = container.getTaskFragmentToken();
+        // Note that taskContainer will not exist before calling #newContainer if the container
+        // is the first embedded TF in the task.
+        final TaskContainer taskContainer = container.getTaskContainer();
+        final Rect taskBounds = taskContainer.getTaskProperties().getTaskMetrics().getBounds();
+        final Rect sanitizedBounds = sanitizeBounds(bounds, intent, taskBounds);
+        final int windowingMode = taskContainer
+                .getWindowingModeForSplitTaskFragment(sanitizedBounds);
+        mPresenter.createTaskFragment(wct, taskFragmentToken, activityInTask.getActivityToken(),
+                sanitizedBounds, windowingMode);
+        mPresenter.updateAnimationParams(wct, taskFragmentToken,
                 TaskFragmentAnimationParams.DEFAULT);
-        return expandedContainer;
+        mPresenter.setTaskFragmentIsolatedNavigation(wct, taskFragmentToken,
+                overlayTag != null && !sanitizedBounds.isEmpty());
+
+        return container;
+    }
+
+    /**
+     * Returns the expanded bounds if the {@code bounds} violate minimum dimension or are not fully
+     * covered by the task bounds. Otherwise, returns {@code bounds}.
+     */
+    @NonNull
+    private static Rect sanitizeBounds(@NonNull Rect bounds, @NonNull Intent intent,
+                                       @NonNull Rect taskBounds) {
+        if (bounds.isEmpty()) {
+            // Don't need to check if the bounds follows the task bounds.
+            return bounds;
+        }
+        if (boundsSmallerThanMinDimensions(bounds, getMinDimensions(intent))) {
+            // Expand the bounds if the bounds are smaller than minimum dimensions.
+            return new Rect();
+        }
+        if (!taskBounds.contains(bounds)) {
+            // Expand the bounds if the bounds exceed the task bounds.
+            return new Rect();
+        }
+        return bounds;
     }
 
     /**
@@ -1449,8 +1497,7 @@
         final SplitContainer splitContainer = getActiveSplitForContainer(existingContainer);
         final TaskContainer.TaskProperties taskProperties = mPresenter
                 .getTaskProperties(primaryActivity);
-        final WindowMetrics taskWindowMetrics = getTaskWindowMetrics(
-                taskProperties.getConfiguration());
+        final WindowMetrics taskWindowMetrics = taskProperties.getTaskMetrics();
         final SplitAttributes calculatedSplitAttributes = mPresenter.computeSplitAttributes(
                 taskProperties, splitRule, splitRule.getDefaultSplitAttributes(),
                 getActivityIntentMinDimensionsPair(primaryActivity, intent));
@@ -1519,14 +1566,22 @@
     TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
             @NonNull Activity activityInTask, int taskId) {
         return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
-                activityInTask, taskId, null /* pairedPrimaryContainer */);
+                activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */);
     }
 
     @GuardedBy("mLock")
     TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
             @NonNull Activity activityInTask, int taskId) {
         return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
-                activityInTask, taskId, null /* pairedPrimaryContainer */);
+                activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */);
+    }
+
+    @GuardedBy("mLock")
+    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
+                                       @NonNull Activity activityInTask, int taskId,
+                                       @NonNull TaskFragmentContainer pairedPrimaryContainer) {
+        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
+                activityInTask, taskId, pairedPrimaryContainer, null /* tag */);
     }
 
     /**
@@ -1540,11 +1595,14 @@
      * @param taskId                    parent Task of the new TaskFragment.
      * @param pairedPrimaryContainer    the paired primary {@link TaskFragmentContainer}. When it is
      *                                  set, the new container will be added right above it.
+     * @param overlayTag                The tag for the new created overlay container. It must be
+     *                                  needed if {@code isOverlay} is {@code true}. Otherwise,
+     *                                  it should be {@code null}.
      */
     @GuardedBy("mLock")
     TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
             @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
-            @Nullable TaskFragmentContainer pairedPrimaryContainer) {
+            @Nullable TaskFragmentContainer pairedPrimaryContainer, @Nullable String overlayTag) {
         if (activityInTask == null) {
             throw new IllegalArgumentException("activityInTask must not be null,");
         }
@@ -1553,7 +1611,7 @@
         }
         final TaskContainer taskContainer = mTaskContainers.get(taskId);
         final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
-                pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer);
+                pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer, overlayTag);
         return container;
     }
 
@@ -1693,31 +1751,6 @@
     }
 
     /**
-     * Returns the topmost not finished container in Task of given task id.
-     */
-    @GuardedBy("mLock")
-    @Nullable
-    TaskFragmentContainer getTopActiveContainer(int taskId) {
-        final TaskContainer taskContainer = mTaskContainers.get(taskId);
-        if (taskContainer == null) {
-            return null;
-        }
-        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
-        for (int i = containers.size() - 1; i >= 0; i--) {
-            final TaskFragmentContainer container = containers.get(i);
-            if (!container.isFinished() && (container.getRunningActivityCount() > 0
-                    // We may be waiting for the top TaskFragment to become non-empty after
-                    // creation. In that case, we don't want to treat the TaskFragment below it as
-                    // top active, otherwise it may incorrectly launch placeholder on top of the
-                    // pending TaskFragment.
-                    || container.isWaitingActivityAppear())) {
-                return container;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Updates the presentation of the container. If the container is part of the split or should
      * have a placeholder, it will also update the other part of the split.
      */
@@ -1754,13 +1787,12 @@
      * Updates {@link SplitContainer} with the given {@link SplitAttributes} if the
      * {@link SplitContainer} is the top most and not finished. If passed {@link SplitAttributes}
      * are {@code null}, the {@link SplitAttributes} will be calculated with
-     * {@link SplitPresenter#computeSplitAttributes(TaskContainer.TaskProperties, SplitRule, Pair)}.
+     * {@link SplitPresenter#computeSplitAttributes}.
      *
      * @param splitContainer The {@link SplitContainer} to update
      * @param splitAttributes Update with this {@code splitAttributes} if it is not {@code null}.
      *                        Otherwise, use the value calculated by
-     *                        {@link SplitPresenter#computeSplitAttributes(
-     *                        TaskContainer.TaskProperties, SplitRule, Pair)}
+     *                        {@link SplitPresenter#computeSplitAttributes}
      *
      * @return {@code true} if the update succeed. Otherwise, returns {@code false}.
      */
@@ -1906,7 +1938,8 @@
     /** Whether or not to allow activity in this container to launch placeholder. */
     @GuardedBy("mLock")
     private boolean allowLaunchPlaceholder(@NonNull TaskFragmentContainer container) {
-        final TaskFragmentContainer topContainer = getTopActiveContainer(container.getTaskId());
+        final TaskFragmentContainer topContainer = container.getTaskContainer()
+                .getTopNonFinishingTaskFragmentContainer();
         if (container != topContainer) {
             // The container is not the top most.
             if (!container.isVisible()) {
@@ -2255,6 +2288,96 @@
         return shouldRetainAssociatedContainer(finishingContainer, associatedContainer);
     }
 
+    /**
+     * Gets all overlay containers from all tasks in this process, or an empty list if there's
+     * no overlay container.
+     * <p>
+     * Note that we only support one overlay container for each task, but an app could have multiple
+     * tasks.
+     */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    @NonNull
+    List<TaskFragmentContainer> getAllOverlayTaskFragmentContainers() {
+        final List<TaskFragmentContainer> overlayContainers = new ArrayList<>();
+        for (int i = 0; i < mTaskContainers.size(); i++) {
+            final TaskContainer taskContainer = mTaskContainers.valueAt(i);
+            final TaskFragmentContainer overlayContainer = taskContainer.getOverlayContainer();
+            if (overlayContainer != null) {
+                overlayContainers.add(overlayContainer);
+            }
+        }
+        return overlayContainers;
+    }
+
+    @VisibleForTesting
+    // Suppress GuardedBy warning because lint ask to mark this method as
+    // @GuardedBy(container.mController.mLock), which is mLock itself
+    @SuppressWarnings("GuardedBy")
+    @GuardedBy("mLock")
+    @Nullable
+    TaskFragmentContainer createOrUpdateOverlayTaskFragmentIfNeeded(
+            @NonNull WindowContainerTransaction wct,
+            @NonNull OverlayCreateParams overlayCreateParams, int launchTaskId,
+            @NonNull Intent intent, @NonNull Activity launchActivity) {
+        final int taskId = overlayCreateParams.getTaskId();
+        if (taskId != launchTaskId) {
+            // The task ID doesn't match the launch activity's. Cannot determine the host task
+            // to launch the overlay.
+            throw new IllegalArgumentException("The task ID of "
+                    + "OverlayCreateParams#launchingActivity must match the task ID of "
+                    + "the activity to #startActivity with the activity options that takes "
+                    + "OverlayCreateParams.");
+        }
+        final List<TaskFragmentContainer> overlayContainers =
+                getAllOverlayTaskFragmentContainers();
+        final String overlayTag = overlayCreateParams.getTag();
+
+        // If the requested bounds of OverlayCreateParams are smaller than minimum dimensions
+        // specified by Intent, expand the overlay container to fill the parent task instead.
+        final Rect bounds = overlayCreateParams.getBounds();
+        final Size minDimensions = getMinDimensions(intent);
+        final boolean shouldExpandContainer = boundsSmallerThanMinDimensions(bounds,
+                minDimensions);
+        if (!overlayContainers.isEmpty()) {
+            for (final TaskFragmentContainer overlayContainer : overlayContainers) {
+                if (!overlayTag.equals(overlayContainer.getOverlayTag())
+                        && taskId == overlayContainer.getTaskId()) {
+                    // If there's an overlay container with different tag shown in the same
+                    // task, dismiss the existing overlay container.
+                    overlayContainer.finish(false /* shouldFinishDependant */, mPresenter,
+                            wct, SplitController.this);
+                }
+                if (overlayTag.equals(overlayContainer.getOverlayTag())
+                        && taskId != overlayContainer.getTaskId()) {
+                    // If there's an overlay container with same tag in a different task,
+                    // dismiss the overlay container since the tag must be unique per process.
+                    overlayContainer.finish(false /* shouldFinishDependant */, mPresenter,
+                            wct, SplitController.this);
+                }
+                if (overlayTag.equals(overlayContainer.getOverlayTag())
+                        && taskId == overlayContainer.getTaskId()) {
+                    // If there's an overlay container with the same tag and task ID, we treat
+                    // the OverlayCreateParams as the update to the container.
+                    final Rect taskBounds = overlayContainer.getTaskContainer().getTaskProperties()
+                            .getTaskMetrics().getBounds();
+                    final IBinder overlayToken = overlayContainer.getTaskFragmentToken();
+                    final Rect sanitizedBounds = sanitizeBounds(bounds, intent, taskBounds);
+                    mPresenter.resizeTaskFragment(wct, overlayToken, sanitizedBounds);
+                    mPresenter.setTaskFragmentIsolatedNavigation(wct, overlayToken,
+                            !sanitizedBounds.isEmpty());
+                    // We can just return the updated overlay container and don't need to
+                    // check other condition since we only have one OverlayCreateParams, and
+                    // if the tag and task are matched, it's impossible to match another task
+                    // or tag since tags and tasks are all unique.
+                    return overlayContainer;
+                }
+            }
+        }
+        return createEmptyContainer(wct, intent, taskId,
+                (shouldExpandContainer ? new Rect() : bounds), launchActivity, overlayTag);
+    }
+
     private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter {
 
         @Override
@@ -2417,8 +2540,16 @@
                 final TaskFragmentContainer launchedInTaskFragment;
                 if (launchingActivity != null) {
                     final int taskId = getTaskId(launchingActivity);
-                    launchedInTaskFragment = resolveStartActivityIntent(wct, taskId, intent,
-                            launchingActivity);
+                    final OverlayCreateParams overlayCreateParams =
+                            OverlayCreateParams.fromBundle(options);
+                    if (Flags.activityEmbeddingOverlayPresentationFlag()
+                            && overlayCreateParams != null) {
+                        launchedInTaskFragment = createOrUpdateOverlayTaskFragmentIfNeeded(wct,
+                                overlayCreateParams, taskId, intent, launchingActivity);
+                    } else {
+                        launchedInTaskFragment = resolveStartActivityIntent(wct, taskId, intent,
+                                launchingActivity);
+                    }
                 } else {
                     launchedInTaskFragment = resolveStartActivityIntentFromNonActivityContext(wct,
                             intent);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index d894487..faf7c39 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -30,12 +30,10 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.util.DisplayMetrics;
 import android.util.LayoutDirection;
 import android.util.Pair;
 import android.util.Size;
 import android.view.View;
-import android.view.WindowInsets;
 import android.view.WindowMetrics;
 import android.window.TaskFragmentAnimationParams;
 import android.window.TaskFragmentCreationParams;
@@ -307,8 +305,8 @@
         }
 
         final int taskId = primaryContainer.getTaskId();
-        final TaskFragmentContainer secondaryContainer = mController.newContainer(
-                null /* pendingAppearedActivity */, activityIntent, launchingActivity, taskId,
+        final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
+                launchingActivity, taskId,
                 // Pass in the primary container to make sure it is added right above the primary.
                 primaryContainer);
         final TaskContainer taskContainer = mController.getTaskContainer(taskId);
@@ -390,14 +388,27 @@
             return;
         }
 
-        setTaskFragmentIsolatedNavigation(wct, secondaryContainer.getTaskFragmentToken(),
-                !isStacked /* isolatedNav */);
+        setTaskFragmentIsolatedNavigation(wct, secondaryContainer, !isStacked /* isolatedNav */);
         if (isStacked && !splitPinRule.isSticky()) {
             secondaryContainer.getTaskContainer().removeSplitPinContainer();
         }
     }
 
     /**
+     * Sets whether to enable isolated navigation for this {@link TaskFragmentContainer}
+     */
+    void setTaskFragmentIsolatedNavigation(@NonNull WindowContainerTransaction wct,
+                                           @NonNull TaskFragmentContainer taskFragmentContainer,
+                                           boolean isolatedNavigationEnabled) {
+        if (taskFragmentContainer.isIsolatedNavigationEnabled() == isolatedNavigationEnabled) {
+            return;
+        }
+        taskFragmentContainer.setIsolatedNavigationEnabled(isolatedNavigationEnabled);
+        setTaskFragmentIsolatedNavigation(wct, taskFragmentContainer.getTaskFragmentToken(),
+                isolatedNavigationEnabled);
+    }
+
+    /**
      * Resizes the task fragment if it was already registered. Skips the operation if the container
      * creation has not been reported from the server yet.
      */
@@ -618,7 +629,7 @@
             @NonNull SplitRule rule, @NonNull SplitAttributes defaultSplitAttributes,
             @Nullable Pair<Size, Size> minDimensionsPair) {
         final Configuration taskConfiguration = taskProperties.getConfiguration();
-        final WindowMetrics taskWindowMetrics = getTaskWindowMetrics(taskConfiguration);
+        final WindowMetrics taskWindowMetrics = taskProperties.getTaskMetrics();
         final Function<SplitAttributesCalculatorParams, SplitAttributes> calculator =
                 mController.getSplitAttributesCalculator();
         final boolean areDefaultConstraintsSatisfied = rule.checkParentMetrics(taskWindowMetrics);
@@ -713,11 +724,15 @@
         return new Size(windowLayout.minWidth, windowLayout.minHeight);
     }
 
-    private static boolean boundsSmallerThanMinDimensions(@NonNull Rect bounds,
+    static boolean boundsSmallerThanMinDimensions(@NonNull Rect bounds,
             @Nullable Size minDimensions) {
         if (minDimensions == null) {
             return false;
         }
+        // Empty bounds mean the bounds follow the parent host task's bounds. Skip the check.
+        if (bounds.isEmpty()) {
+            return false;
+        }
         return bounds.width() < minDimensions.getWidth()
                 || bounds.height() < minDimensions.getHeight();
     }
@@ -1066,14 +1081,6 @@
 
     @NonNull
     WindowMetrics getTaskWindowMetrics(@NonNull Activity activity) {
-        return getTaskWindowMetrics(getTaskProperties(activity).getConfiguration());
-    }
-
-    @NonNull
-    static WindowMetrics getTaskWindowMetrics(@NonNull Configuration taskConfiguration) {
-        final Rect taskBounds = taskConfiguration.windowConfiguration.getBounds();
-        // TODO(b/190433398): Supply correct insets.
-        final float density = taskConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
-        return new WindowMetrics(taskBounds, WindowInsets.CONSUMED, density);
+        return getTaskProperties(activity).getTaskMetrics();
     }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 9a0769a..9e53380 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -30,7 +30,10 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.util.ArraySet;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.WindowInsets;
+import android.view.WindowMetrics;
 import android.window.TaskFragmentInfo;
 import android.window.TaskFragmentParentInfo;
 import android.window.WindowContainerTransaction;
@@ -61,6 +64,10 @@
     @Nullable
     private SplitPinContainer mSplitPinContainer;
 
+    /** The overlay container in this Task. */
+    @Nullable
+    private TaskFragmentContainer mOverlayContainer;
+
     @NonNull
     private final Configuration mConfiguration;
 
@@ -184,11 +191,20 @@
 
     @Nullable
     TaskFragmentContainer getTopNonFinishingTaskFragmentContainer(boolean includePin) {
+        return getTopNonFinishingTaskFragmentContainer(includePin, false /* includeOverlay */);
+    }
+
+    @Nullable
+    TaskFragmentContainer getTopNonFinishingTaskFragmentContainer(boolean includePin,
+                                                                  boolean includeOverlay) {
         for (int i = mContainers.size() - 1; i >= 0; i--) {
             final TaskFragmentContainer container = mContainers.get(i);
             if (!includePin && isTaskFragmentContainerPinned(container)) {
                 continue;
             }
+            if (!includeOverlay && container.isOverlay()) {
+                continue;
+            }
             if (!container.isFinished()) {
                 return container;
             }
@@ -221,6 +237,12 @@
         return null;
     }
 
+    /** Returns the overlay container in the task, or {@code null} if it doesn't exist. */
+    @Nullable
+    TaskFragmentContainer getOverlayContainer() {
+        return mOverlayContainer;
+    }
+
     int indexOf(@NonNull TaskFragmentContainer child) {
         return mContainers.indexOf(child);
     }
@@ -311,8 +333,8 @@
         onTaskFragmentContainerUpdated();
     }
 
-    void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
-        mContainers.removeAll(taskFragmentContainer);
+    void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainers) {
+        mContainers.removeAll(taskFragmentContainers);
         onTaskFragmentContainerUpdated();
     }
 
@@ -332,6 +354,15 @@
     }
 
     private void onTaskFragmentContainerUpdated() {
+        // TODO(b/300211704): Find a better mechanism to handle the z-order in case we introduce
+        //  another special container that should also be on top in the future.
+        updateSplitPinContainerIfNecessary();
+        // Update overlay container after split pin container since the overlay should be on top of
+        // pin container.
+        updateOverlayContainerIfNecessary();
+    }
+
+    private void updateSplitPinContainerIfNecessary() {
         if (mSplitPinContainer == null) {
             return;
         }
@@ -344,10 +375,7 @@
         }
 
         // Ensure the pinned container is top-most.
-        if (pinnedContainerIndex != mContainers.size() - 1) {
-            mContainers.remove(pinnedContainer);
-            mContainers.add(pinnedContainer);
-        }
+        moveContainerToLastIfNecessary(pinnedContainer);
 
         // Update the primary container adjacent to the pinned container if needed.
         final TaskFragmentContainer adjacentContainer =
@@ -359,6 +387,31 @@
         }
     }
 
+    private void updateOverlayContainerIfNecessary() {
+        final List<TaskFragmentContainer> overlayContainers = mContainers.stream()
+                .filter(TaskFragmentContainer::isOverlay).toList();
+        if (overlayContainers.size() > 1) {
+            throw new IllegalStateException("There must be at most one overlay container per Task");
+        }
+        mOverlayContainer = overlayContainers.isEmpty() ? null : overlayContainers.get(0);
+        if (mOverlayContainer != null) {
+            moveContainerToLastIfNecessary(mOverlayContainer);
+        }
+    }
+
+    /** Moves the {@code container} to the last to align taskFragments' z-order. */
+    private void moveContainerToLastIfNecessary(@NonNull TaskFragmentContainer container) {
+        final int index = mContainers.indexOf(container);
+        if (index < 0) {
+            Log.w(TAG, "The container:" + container + " is not in the container list!");
+            return;
+        }
+        if (index != mContainers.size() - 1) {
+            mContainers.remove(container);
+            mContainers.add(container);
+        }
+    }
+
     /**
      * Gets the descriptors of split states in this Task.
      *
@@ -398,6 +451,15 @@
             return mConfiguration;
         }
 
+        /** A helper method to return task {@link WindowMetrics} from this {@link TaskProperties} */
+        @NonNull
+        WindowMetrics getTaskMetrics() {
+            final Rect taskBounds = mConfiguration.windowConfiguration.getBounds();
+            // TODO(b/190433398): Supply correct insets.
+            final float density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+            return new WindowMetrics(taskBounds, WindowInsets.CONSUMED, density);
+        }
+
         /** Translates the given absolute bounds to relative bounds in this Task coordinate. */
         void translateAbsoluteBoundsToRelativeBounds(@NonNull Rect inOutBounds) {
             if (inOutBounds.isEmpty()) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 0a694b5..3e7f99b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -102,6 +102,9 @@
      */
     private final List<IBinder> mActivitiesToFinishOnExit = new ArrayList<>();
 
+    @Nullable
+    private final String mOverlayTag;
+
     /** Indicates whether the container was cleaned up after the last activity was removed. */
     private boolean mIsFinished;
 
@@ -157,15 +160,32 @@
      */
     private boolean mHasCrossProcessActivities;
 
+    /** Whether this TaskFragment enable isolated navigation. */
+    private boolean mIsIsolatedNavigationEnabled;
+
+    /**
+     * @see #TaskFragmentContainer(Activity, Intent, TaskContainer, SplitController,
+     * TaskFragmentContainer, String)
+     */
+    TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
+                          @Nullable Intent pendingAppearedIntent,
+                          @NonNull TaskContainer taskContainer,
+                          @NonNull SplitController controller,
+                          @Nullable TaskFragmentContainer pairedPrimaryContainer) {
+        this(pendingAppearedActivity, pendingAppearedIntent, taskContainer,
+                controller, pairedPrimaryContainer, null /* overlayTag */);
+    }
+
     /**
      * Creates a container with an existing activity that will be re-parented to it in a window
      * container transaction.
      * @param pairedPrimaryContainer    when it is set, the new container will be add right above it
+     * @param overlayTag                Sets to indicate this taskFragment is an overlay container
      */
     TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
             @Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
             @NonNull SplitController controller,
-            @Nullable TaskFragmentContainer pairedPrimaryContainer) {
+            @Nullable TaskFragmentContainer pairedPrimaryContainer, @Nullable String overlayTag) {
         if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
                 || (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
             throw new IllegalArgumentException(
@@ -174,6 +194,8 @@
         mController = controller;
         mToken = new Binder("TaskFragmentContainer");
         mTaskContainer = taskContainer;
+        mOverlayTag = overlayTag;
+
         if (pairedPrimaryContainer != null) {
             // The TaskFragment will be positioned right above the paired container.
             if (pairedPrimaryContainer.getTaskContainer() != taskContainer) {
@@ -786,6 +808,16 @@
         mLastCompanionTaskFragment = fragmentToken;
     }
 
+    /** Returns whether to enable isolated navigation or not. */
+    boolean isIsolatedNavigationEnabled() {
+        return mIsIsolatedNavigationEnabled;
+    }
+
+    /** Sets whether to enable isolated navigation or not. */
+    void setIsolatedNavigationEnabled(boolean isolatedNavigationEnabled) {
+        mIsIsolatedNavigationEnabled = isolatedNavigationEnabled;
+    }
+
     /**
      * Adds the pending appeared activity that has requested to be launched in this task fragment.
      * @see android.app.ActivityClient#isRequestedToLaunchInTaskFragment
@@ -863,6 +895,20 @@
         return mTaskContainer.indexOf(this) > mTaskContainer.indexOf(other);
     }
 
+    /** Returns whether this taskFragment container is an overlay container. */
+    boolean isOverlay() {
+        return mOverlayTag != null;
+    }
+
+    /**
+     * Returns the tag specified in {@link OverlayCreateParams#getTag()}. {@code null} if this
+     * taskFragment container is not an overlay container.
+     */
+    @Nullable
+    String getOverlayTag() {
+        return mOverlayTag;
+    }
+
     @Override
     public String toString() {
         return toString(true /* includeContainersToFinishOnExit */);
@@ -881,6 +927,7 @@
                 + " topNonFinishingActivity=" + getTopNonFinishingActivity()
                 + " runningActivityCount=" + getRunningActivityCount()
                 + " isFinished=" + mIsFinished
+                + " overlayTag=" + mOverlayTag
                 + " lastRequestedBounds=" + mLastRequestedBounds
                 + " pendingAppearedActivities=" + mPendingAppearedActivities
                 + (includeContainersToFinishOnExit ? " containersToFinishOnExit="
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
index ed2ff2d..4ddbd13 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -36,6 +36,7 @@
         "androidx.test.runner",
         "androidx.test.rules",
         "androidx.test.ext.junit",
+        "flag-junit",
         "mockito-target-extended-minus-junit4",
         "truth",
         "testables",
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
new file mode 100644
index 0000000..405f0b2
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPairRuleBuilder;
+import static androidx.window.extensions.embedding.OverlayCreateParams.KEY_OVERLAY_CREATE_PARAMS;
+import static androidx.window.extensions.embedding.OverlayCreateParams.KEY_OVERLAY_CREATE_PARAMS_BOUNDS;
+import static androidx.window.extensions.embedding.OverlayCreateParams.KEY_OVERLAY_CREATE_PARAMS_TAG;
+import static androidx.window.extensions.embedding.OverlayCreateParams.KEY_OVERLAY_CREATE_PARAMS_TASK_ID;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
+import androidx.window.extensions.layout.WindowLayoutComponentImpl;
+import androidx.window.extensions.layout.WindowLayoutInfo;
+
+import com.android.window.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test class for overlay presentation feature.
+ *
+ * Build/Install/Run:
+ *  atest WMJetpackUnitTests:OverlayPresentationTest
+ */
+// Suppress GuardedBy warning on unit tests
+@SuppressWarnings("GuardedBy")
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class OverlayPresentationTest {
+
+    @Rule
+    public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
+
+    private static final OverlayCreateParams TEST_OVERLAY_CREATE_PARAMS =
+            new OverlayCreateParams(TASK_ID, "test,", new Rect(0, 0, 200, 200));
+
+    private SplitController.ActivityStartMonitor mMonitor;
+
+    private Intent mIntent;
+
+    private TaskFragmentContainer mOverlayContainer1;
+
+    private TaskFragmentContainer mOverlayContainer2;
+
+    private Activity mActivity;
+    @Mock
+    private Resources mActivityResources;
+
+    @Mock
+    private WindowContainerTransaction mTransaction;
+    @Mock
+    private Handler mHandler;
+    @Mock
+    private WindowLayoutComponentImpl mWindowLayoutComponent;
+
+    private SplitController mSplitController;
+    private SplitPresenter mSplitPresenter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
+                .getCurrentWindowLayoutInfo(anyInt(), any());
+        DeviceStateManagerFoldingFeatureProducer producer =
+                mock(DeviceStateManagerFoldingFeatureProducer.class);
+        mSplitController = new SplitController(mWindowLayoutComponent, producer);
+        mSplitPresenter = mSplitController.mPresenter;
+        mMonitor = mSplitController.getActivityStartMonitor();
+        mIntent = new Intent();
+
+        spyOn(mSplitController);
+        spyOn(mSplitPresenter);
+        spyOn(mMonitor);
+
+        doNothing().when(mSplitPresenter).applyTransaction(any(), anyInt(), anyBoolean());
+        final Configuration activityConfig = new Configuration();
+        activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
+        activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
+        doReturn(activityConfig).when(mActivityResources).getConfiguration();
+        doReturn(mHandler).when(mSplitController).getHandler();
+        mActivity = createMockActivity();
+
+        mSetFlagRule.enableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG);
+    }
+
+    /** Creates a mock activity in the organizer process. */
+    @NonNull
+    private Activity createMockActivity() {
+        final Activity activity = mock(Activity.class);
+        doReturn(mActivityResources).when(activity).getResources();
+        final IBinder activityToken = new Binder();
+        doReturn(activityToken).when(activity).getActivityToken();
+        doReturn(activity).when(mSplitController).getActivity(activityToken);
+        doReturn(TASK_ID).when(activity).getTaskId();
+        doReturn(new ActivityInfo()).when(activity).getActivityInfo();
+        doReturn(DEFAULT_DISPLAY).when(activity).getDisplayId();
+        return activity;
+    }
+
+    @Test
+    public void testOverlayCreateParamsFromBundle() {
+        assertThat(OverlayCreateParams.fromBundle(new Bundle())).isNull();
+
+        assertThat(OverlayCreateParams.fromBundle(createOverlayCreateParamsTestBundle()))
+                .isEqualTo(TEST_OVERLAY_CREATE_PARAMS);
+    }
+
+    @Test
+    public void testStartActivity_overlayFeatureDisabled_notInvokeCreateOverlayContainer() {
+        mSetFlagRule.disableFlags(Flags.FLAG_ACTIVITY_EMBEDDING_OVERLAY_PRESENTATION_FLAG);
+
+        mMonitor.onStartActivity(mActivity, mIntent, createOverlayCreateParamsTestBundle());
+
+        verify(mSplitController, never()).createOrUpdateOverlayTaskFragmentIfNeeded(any(), any(),
+                anyInt(), any(), any());
+    }
+
+    @NonNull
+    private static Bundle createOverlayCreateParamsTestBundle() {
+        final Bundle bundle = new Bundle();
+
+        final Bundle paramsBundle = new Bundle();
+        paramsBundle.putInt(KEY_OVERLAY_CREATE_PARAMS_TASK_ID,
+                TEST_OVERLAY_CREATE_PARAMS.getTaskId());
+        paramsBundle.putString(KEY_OVERLAY_CREATE_PARAMS_TAG, TEST_OVERLAY_CREATE_PARAMS.getTag());
+        paramsBundle.putObject(KEY_OVERLAY_CREATE_PARAMS_BOUNDS,
+                TEST_OVERLAY_CREATE_PARAMS.getBounds());
+
+        bundle.putBundle(KEY_OVERLAY_CREATE_PARAMS, paramsBundle);
+
+        return bundle;
+    }
+
+    @Test
+    public void testGetOverlayContainers() {
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers()).isEmpty();
+
+        final TaskFragmentContainer overlayContainer1 =
+                createTestOverlayContainer(TASK_ID, "test1");
+
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer1);
+
+        assertThrows(
+                "The exception must throw if there are two overlay containers in the same task.",
+                IllegalStateException.class,
+                () -> createTestOverlayContainer(TASK_ID, "test2"));
+
+        final TaskFragmentContainer overlayContainer3 =
+                createTestOverlayContainer(TASK_ID + 1, "test3");
+
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer1, overlayContainer3);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_taskIdNotMatch_throwException() {
+        assertThrows("The method must return null due to task mismatch between"
+                + " launchingActivity and OverlayCreateParams", IllegalArgumentException.class,
+                () -> createOrUpdateOverlayTaskFragmentIfNeeded(
+                        TEST_OVERLAY_CREATE_PARAMS, TASK_ID + 1));
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_anotherTagInTask_dismissOverlay() {
+        createExistingOverlayContainers();
+
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                new OverlayCreateParams(TASK_ID, "test3", new Rect(0, 0, 100, 100)), TASK_ID);
+
+        assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
+                + " is launched to the same task")
+                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(mOverlayContainer2, overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_sameTagAnotherTask_dismissOverlay() {
+        createExistingOverlayContainers();
+
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                new OverlayCreateParams(TASK_ID + 2, "test1", new Rect(0, 0, 100, 100)),
+                TASK_ID + 2);
+
+        assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
+                + " is launched with the same tag as an existing overlay container in a different "
+                + "task")
+                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(mOverlayContainer2, overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_sameTagAndTask_updateOverlay() {
+        createExistingOverlayContainers();
+
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                new OverlayCreateParams(TASK_ID, "test1", bounds),
+                TASK_ID);
+
+        assertWithMessage("overlayContainer1 must be updated since the new overlay container"
+                + " is launched with the same tag and task")
+                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(mOverlayContainer1, mOverlayContainer2);
+
+        assertThat(overlayContainer).isEqualTo(mOverlayContainer1);
+        verify(mSplitPresenter).resizeTaskFragment(eq(mTransaction),
+                eq(mOverlayContainer1.getTaskFragmentToken()), eq(bounds));
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_dismissMultipleOverlays() {
+        createExistingOverlayContainers();
+
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                new OverlayCreateParams(TASK_ID, "test2", new Rect(0, 0, 100, 100)),
+                TASK_ID);
+
+        // OverlayContainer1 is dismissed since new container is launched in the same task with
+        // different tag. OverlayContainer2 is dismissed since new container is launched with the
+        // same tag in different task.
+        assertWithMessage("overlayContainer1 and overlayContainer2 must be dismissed")
+                .that(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+    }
+
+    private void createExistingOverlayContainers() {
+        mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1");
+        mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2");
+        List<TaskFragmentContainer> overlayContainers = mSplitController
+                .getAllOverlayTaskFragmentContainers();
+        assertThat(overlayContainers).containsExactly(mOverlayContainer1, mOverlayContainer2);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_smallerThanMinDimens_expandOverlay() {
+        mIntent.setComponent(new ComponentName(ApplicationProvider.getApplicationContext(),
+                MinimumDimensionActivity.class));
+
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                TEST_OVERLAY_CREATE_PARAMS, TASK_ID);
+        final IBinder overlayToken = overlayContainer.getTaskFragmentToken();
+
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+        assertThat(overlayContainer.areLastRequestedBoundsEqual(new Rect())).isTrue();
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, overlayToken,
+                false);
+
+        // Call createOrUpdateOverlayTaskFragmentIfNeeded again to check the update case.
+        clearInvocations(mSplitPresenter);
+        createOrUpdateOverlayTaskFragmentIfNeeded(TEST_OVERLAY_CREATE_PARAMS, TASK_ID);
+
+        verify(mSplitPresenter).resizeTaskFragment(mTransaction, overlayToken, new Rect());
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, overlayToken,
+                false);
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_notInTaskBounds_expandOverlay() {
+        final Rect bounds = new Rect(TASK_BOUNDS);
+        bounds.offset(10, 10);
+        final OverlayCreateParams paramsOutsideTaskBounds = new OverlayCreateParams(TASK_ID,
+                "test", bounds);
+
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                paramsOutsideTaskBounds, TASK_ID);
+        final IBinder overlayToken = overlayContainer.getTaskFragmentToken();
+
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+        assertThat(overlayContainer.areLastRequestedBoundsEqual(new Rect())).isTrue();
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, overlayToken,
+                false);
+
+        // Call createOrUpdateOverlayTaskFragmentIfNeeded again to check the update case.
+        clearInvocations(mSplitPresenter);
+        createOrUpdateOverlayTaskFragmentIfNeeded(paramsOutsideTaskBounds, TASK_ID);
+
+        verify(mSplitPresenter).resizeTaskFragment(mTransaction, overlayToken, new Rect());
+        verify(mSplitPresenter).setTaskFragmentIsolatedNavigation(mTransaction, overlayToken,
+                false);
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+    }
+
+    @Test
+    public void testCreateOrUpdateOverlayTaskFragmentIfNeeded_createOverlay() {
+        final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
+                TEST_OVERLAY_CREATE_PARAMS, TASK_ID);
+
+        assertThat(mSplitController.getAllOverlayTaskFragmentContainers())
+                .containsExactly(overlayContainer);
+        assertThat(overlayContainer.getTaskId()).isEqualTo(TASK_ID);
+        assertThat(overlayContainer
+                .areLastRequestedBoundsEqual(TEST_OVERLAY_CREATE_PARAMS.getBounds())).isTrue();
+        assertThat(overlayContainer.getOverlayTag()).isEqualTo(TEST_OVERLAY_CREATE_PARAMS.getTag());
+    }
+
+    @Test
+    public void testGetTopNonFishingTaskFragmentContainerWithOverlay() {
+        final TaskFragmentContainer overlayContainer =
+                createTestOverlayContainer(TASK_ID, "test1");
+
+        // Add a SplitPinContainer, the overlay should be on top
+        final Activity primaryActivity = createMockActivity();
+        final Activity secondaryActivity = createMockActivity();
+
+        final TaskFragmentContainer primaryContainer =
+                createMockTaskFragmentContainer(primaryActivity);
+        final TaskFragmentContainer secondaryContainer =
+                createMockTaskFragmentContainer(secondaryActivity);
+        final SplitPairRule splitPairRule = createSplitPairRuleBuilder(
+                activityActivityPair -> true /* activityPairPredicate */,
+                activityIntentPair -> true  /* activityIntentPairPredicate */,
+                parentWindowMetrics -> true /* parentWindowMetricsPredicate */).build();
+        mSplitController.registerSplit(mTransaction, primaryContainer, primaryActivity,
+                secondaryContainer, splitPairRule,  splitPairRule.getDefaultSplitAttributes());
+        SplitPinRule splitPinRule = new SplitPinRule.Builder(new SplitAttributes.Builder().build(),
+                parentWindowMetrics -> true /* parentWindowMetricsPredicate */).build();
+        mSplitController.pinTopActivityStack(TASK_ID, splitPinRule);
+        final TaskFragmentContainer topPinnedContainer = mSplitController.getTaskContainer(TASK_ID)
+                .getSplitPinContainer().getSecondaryContainer();
+
+        // Add a normal container after the overlay, the overlay should still on top,
+        // and the SplitPinContainer should also on top of the normal one.
+        final TaskFragmentContainer container = createMockTaskFragmentContainer(mActivity);
+
+        final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
+
+        assertThat(taskContainer.getTaskFragmentContainers())
+                .containsExactly(primaryContainer, container, secondaryContainer, overlayContainer)
+                .inOrder();
+
+        assertWithMessage("The pinned container must be returned excluding the overlay")
+                .that(taskContainer.getTopNonFinishingTaskFragmentContainer())
+                .isEqualTo(topPinnedContainer);
+
+        assertThat(taskContainer.getTopNonFinishingTaskFragmentContainer(false))
+                .isEqualTo(container);
+
+        assertWithMessage("The overlay container must be returned since it's always on top")
+                .that(taskContainer.getTopNonFinishingTaskFragmentContainer(
+                        false /* includePin */, true /* includeOverlay */))
+                .isEqualTo(overlayContainer);
+    }
+
+    /**
+     * A simplified version of {@link SplitController.ActivityStartMonitor
+     * #createOrUpdateOverlayTaskFragmentIfNeeded}
+     */
+    @Nullable
+    private TaskFragmentContainer createOrUpdateOverlayTaskFragmentIfNeeded(
+            @NonNull OverlayCreateParams params, int taskId) {
+        return mSplitController.createOrUpdateOverlayTaskFragmentIfNeeded(mTransaction, params,
+                taskId, mIntent, mActivity);
+    }
+
+    /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
+    @NonNull
+    private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
+        final TaskFragmentContainer container = mSplitController.newContainer(activity,
+                activity.getTaskId());
+        setupTaskFragmentInfo(container, activity);
+        return container;
+    }
+
+    @NonNull
+    private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag) {
+        TaskFragmentContainer overlayContainer = mSplitController.newContainer(
+                null /* pendingAppearedActivity */, mIntent, mActivity, taskId,
+                null /* pairedPrimaryContainer */, tag);
+        setupTaskFragmentInfo(overlayContainer, mActivity);
+        return overlayContainer;
+    }
+
+    private void setupTaskFragmentInfo(@NonNull TaskFragmentContainer container,
+                                       @NonNull Activity activity) {
+        final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity);
+        container.setInfo(mTransaction, info);
+        mSplitPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), info);
+    }
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index d440a3e..96839c5 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -48,18 +48,18 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
-import static com.google.common.truth.Truth.assertWithMessage;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.clearInvocations;
@@ -175,52 +175,6 @@
     }
 
     @Test
-    public void testGetTopActiveContainer() {
-        final TaskContainer taskContainer = createTestTaskContainer();
-        // tf1 has no running activity so is not active.
-        final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
-                new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
-        // tf2 has running activity so is active.
-        final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
-        doReturn(1).when(tf2).getRunningActivityCount();
-        taskContainer.addTaskFragmentContainer(tf2);
-        // tf3 is finished so is not active.
-        final TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
-        doReturn(true).when(tf3).isFinished();
-        doReturn(false).when(tf3).isWaitingActivityAppear();
-        taskContainer.addTaskFragmentContainer(tf3);
-        mSplitController.mTaskContainers.put(TASK_ID, taskContainer);
-
-        assertWithMessage("Must return tf2 because tf3 is not active.")
-                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);
-
-        taskContainer.removeTaskFragmentContainer(tf3);
-
-        assertWithMessage("Must return tf2 because tf2 has running activity.")
-                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);
-
-        taskContainer.removeTaskFragmentContainer(tf2);
-
-        assertWithMessage("Must return tf because we are waiting for tf1 to appear.")
-                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf1);
-
-        final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
-        doReturn(new ArrayList<>()).when(info).getActivities();
-        doReturn(true).when(info).isEmpty();
-        tf1.setInfo(mTransaction, info);
-
-        assertWithMessage("Must return tf because we are waiting for tf1 to become non-empty after"
-                + " creation.")
-                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf1);
-
-        doReturn(false).when(info).isEmpty();
-        tf1.setInfo(mTransaction, info);
-
-        assertWithMessage("Must return null because tf1 becomes empty.")
-                .that(mSplitController.getTopActiveContainer(TASK_ID)).isNull();
-    }
-
-    @Test
     public void testOnTaskFragmentVanished() {
         final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
         doReturn(tf.getTaskFragmentToken()).when(mInfo).getFragmentToken();
@@ -305,7 +259,9 @@
 
         mSplitController.updateContainer(mTransaction, tf);
 
-        verify(mSplitController, never()).getTopActiveContainer(TASK_ID);
+        TaskContainer taskContainer = tf.getTaskContainer();
+        spyOn(taskContainer);
+        verify(taskContainer, never()).getTopNonFinishingTaskFragmentContainer();
 
         // Verify if tf is not in split, dismissPlaceholderIfNecessary won't be called.
         doReturn(false).when(mSplitController).shouldContainerBeExpanded(tf);
@@ -320,7 +276,7 @@
         doReturn(tf).when(splitContainer).getSecondaryContainer();
         doReturn(createTestTaskContainer()).when(splitContainer).getTaskContainer();
         doReturn(createSplitRule(mActivity, mActivity)).when(splitContainer).getSplitRule();
-        final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
+        taskContainer = mSplitController.getTaskContainer(TASK_ID);
         taskContainer.addSplitContainer(splitContainer);
         // Add a mock SplitContainer on top of splitContainer
         final SplitContainer splitContainer2 = mock(SplitContainer.class);
@@ -595,13 +551,12 @@
     }
 
     @Test
-    public void testResolveStartActivityIntent_skipIfPinned() {
+    public void testResolveStartActivityIntent_skipIfIsolatedNavEnabled() {
         final TaskFragmentContainer container = createMockTaskFragmentContainer(mActivity);
-        final TaskContainer taskContainer = container.getTaskContainer();
-        spyOn(taskContainer);
+        container.setIsolatedNavigationEnabled(true);
+
         final Intent intent = new Intent();
         setupSplitRule(mActivity, intent);
-        doReturn(true).when(taskContainer).isTaskFragmentContainerPinned(container);
         assertNull(mSplitController.resolveStartActivityIntent(mTransaction, TASK_ID, intent,
                 mActivity));
     }
@@ -634,7 +589,8 @@
                 false /* isOnReparent */);
 
         assertFalse(result);
-        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
+        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
+                anyString());
     }
 
     @Test
@@ -796,7 +752,8 @@
                 false /* isOnReparent */);
 
         assertTrue(result);
-        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
+        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
+                anyString());
         verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
     }
 
@@ -838,7 +795,8 @@
                 false /* isOnReparent */);
 
         assertTrue(result);
-        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
+        verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any(),
+                anyString());
         verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
     }
 
@@ -1565,9 +1523,9 @@
         addSplitTaskFragments(primaryActivity, thirdActivity);
 
         // Ensure another SplitContainer is added and the pinned TaskFragment still on top
-        assertTrue(taskContainer.getSplitContainers().size() == splitContainerCount + +1);
-        assertTrue(mSplitController.getTopActiveContainer(TASK_ID).getTopNonFinishingActivity()
-                == secondaryActivity);
+        assertEquals(taskContainer.getSplitContainers().size(), splitContainerCount + +1);
+        assertSame(taskContainer.getTopNonFinishingTaskFragmentContainer()
+                .getTopNonFinishingActivity(), secondaryActivity);
     }
 
     /** Creates a mock activity in the organizer process. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 3790f04..d08c573 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.back;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_HOME;
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
@@ -70,7 +71,6 @@
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 
-
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -317,7 +317,11 @@
             executeRemoteCallWithTaskPermission(mController, "setBackToLauncherCallback",
                     (controller) -> controller.registerAnimation(
                             BackNavigationInfo.TYPE_RETURN_TO_HOME,
-                            new BackAnimationRunner(callback, runner)));
+                            new BackAnimationRunner(
+                                    callback,
+                                    runner,
+                                    controller.mContext,
+                                    CUJ_PREDICTIVE_BACK_HOME)));
         }
 
         @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index 431df21..dc413b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.TRANSIT_OLD_UNSET;
 
 import android.annotation.NonNull;
+import android.content.Context;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IRemoteAnimationFinishedCallback;
@@ -27,16 +28,22 @@
 import android.window.IBackAnimationRunner;
 import android.window.IOnBackInvokedCallback;
 
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.wm.shell.common.InteractionJankMonitorUtils;
+
 /**
  * Used to register the animation callback and runner, it will trigger result if gesture was finish
  * before it received IBackAnimationRunner#onAnimationStart, so the controller could continue
  * trigger the real back behavior.
  */
 public class BackAnimationRunner {
+    private static final int NO_CUJ = -1;
     private static final String TAG = "ShellBackPreview";
 
     private final IOnBackInvokedCallback mCallback;
     private final IRemoteAnimationRunner mRunner;
+    private final @InteractionJankMonitor.CujType int mCujType;
+    private final Context mContext;
 
     // Whether we are waiting to receive onAnimationStart
     private boolean mWaitingAnimation;
@@ -45,9 +52,21 @@
     private boolean mAnimationCancelled;
 
     public BackAnimationRunner(
-            @NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner) {
+            @NonNull IOnBackInvokedCallback callback,
+            @NonNull IRemoteAnimationRunner runner,
+            @NonNull Context context,
+            @InteractionJankMonitor.CujType int cujType) {
         mCallback = callback;
         mRunner = runner;
+        mCujType = cujType;
+        mContext = context;
+    }
+
+    public BackAnimationRunner(
+            @NonNull IOnBackInvokedCallback callback,
+            @NonNull IRemoteAnimationRunner runner,
+            @NonNull Context context) {
+        this(callback, runner, context, NO_CUJ);
     }
 
     /** Returns the registered animation runner */
@@ -70,10 +89,17 @@
                 new IRemoteAnimationFinishedCallback.Stub() {
                     @Override
                     public void onAnimationFinished() {
+                        if (shouldMonitorCUJ(apps)) {
+                            InteractionJankMonitorUtils.endTracing(mCujType);
+                        }
                         finishedCallback.run();
                     }
                 };
         mWaitingAnimation = false;
+        if (shouldMonitorCUJ(apps)) {
+            InteractionJankMonitorUtils.beginTracing(
+                    mCujType, mContext, apps[0].leash, /* tag */ null);
+        }
         try {
             getRunner().onAnimationStart(TRANSIT_OLD_UNSET, apps, wallpapers,
                     nonApps, callback);
@@ -82,6 +108,10 @@
         }
     }
 
+    private boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) {
+        return apps.length > 0 && mCujType != NO_CUJ;
+    }
+
     void startGesture() {
         mWaitingAnimation = true;
         mAnimationCancelled = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
index 114486e..24479d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
@@ -19,6 +19,7 @@
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY;
 import static com.android.wm.shell.back.BackAnimationConstants.PROGRESS_COMMIT_THRESHOLD;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 
@@ -135,7 +136,8 @@
     @Inject
     public CrossActivityAnimation(Context context, BackAnimationBackground background) {
         mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
-        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
+        mBackAnimationRunner = new BackAnimationRunner(
+                new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY);
         mBackground = background;
         mEnteringProgressSpring = new SpringAnimation(this, ENTER_PROGRESS_PROP);
         mEnteringProgressSpring.setSpring(new SpringForce()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
index 209d853..fc5ff01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
@@ -20,6 +20,7 @@
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.window.BackEvent.EDGE_RIGHT;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_TASK;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 
 import android.animation.Animator;
@@ -108,6 +109,7 @@
     private final float[] mTmpTranslate = {0, 0, 0};
     private final BackAnimationRunner mBackAnimationRunner;
     private final BackAnimationBackground mBackground;
+    private final Context mContext;
     private RemoteAnimationTarget mEnteringTarget;
     private RemoteAnimationTarget mClosingTarget;
     private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -120,8 +122,10 @@
 
     @Inject
     public CrossTaskBackAnimation(Context context, BackAnimationBackground background) {
+        mContext = context;
         mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
-        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
+        mBackAnimationRunner = new BackAnimationRunner(
+                new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_TASK);
         mBackground = background;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
index aca638c..5254ff4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -19,6 +19,7 @@
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 
 import android.animation.Animator;
@@ -97,7 +98,8 @@
             SurfaceControl.Transaction transaction, Choreographer choreographer) {
         mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
         mBackground = background;
-        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
+        mBackAnimationRunner = new BackAnimationRunner(
+                new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY);
         mCustomAnimationLoader = new CustomAnimationLoader(context);
 
         mProgressSpring = new SpringAnimation(this, ENTER_PROGRESS_PROP);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
new file mode 100644
index 0000000..f561aa5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+
+import static com.android.wm.shell.transition.Transitions.TransitionObserver;
+
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.IBinder;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+import com.android.wm.shell.common.RemoteCallable;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.SingleInstanceRemoteListener;
+import com.android.wm.shell.util.TransitionUtil;
+
+/**
+ * The {@link TransitionObserver} that observes for transitions involving the home
+ * activity. It reports transitions to the caller via {@link IHomeTransitionListener}.
+ */
+public class HomeTransitionObserver implements TransitionObserver,
+        RemoteCallable<HomeTransitionObserver> {
+    private final SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener>
+            mListener;
+
+    private @NonNull final Context mContext;
+    private @NonNull final ShellExecutor mMainExecutor;
+    private @NonNull final Transitions mTransitions;
+
+    public HomeTransitionObserver(@NonNull Context context,
+            @NonNull ShellExecutor mainExecutor,
+            @NonNull Transitions transitions) {
+        mContext = context;
+        mMainExecutor = mainExecutor;
+        mTransitions = transitions;
+
+        mListener = new SingleInstanceRemoteListener<>(this,
+                c -> mTransitions.registerObserver(this),
+                c -> mTransitions.unregisterObserver(this));
+
+    }
+
+    @Override
+    public void onTransitionReady(@NonNull IBinder transition,
+            @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction) {
+        for (TransitionInfo.Change change : info.getChanges()) {
+            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+            if (taskInfo == null || taskInfo.taskId == -1) {
+                continue;
+            }
+
+            final int mode = change.getMode();
+            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
+                    && TransitionUtil.isOpenOrCloseMode(mode)) {
+                mListener.call(l -> l.onHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)));
+            }
+        }
+    }
+
+    @Override
+    public void onTransitionStarting(@NonNull IBinder transition) {}
+
+    @Override
+    public void onTransitionMerged(@NonNull IBinder merged,
+            @NonNull IBinder playing) {}
+
+    @Override
+    public void onTransitionFinished(@NonNull IBinder transition,
+            boolean aborted) {}
+
+    /**
+     * Sets the home transition listener that receives any transitions resulting in a change of
+     *
+     */
+    public void setHomeTransitionListener(IHomeTransitionListener listener) {
+        if (listener != null) {
+            mListener.register(listener);
+        } else {
+            mListener.unregister();
+        }
+    }
+
+    @Override
+    public Context getContext() {
+        return mContext;
+    }
+
+    @Override
+    public ShellExecutor getRemoteCallExecutor() {
+        return mMainExecutor;
+    }
+
+    /**
+     * Invalidates this controller, preventing future calls to send updates.
+     */
+    public void invalidate() {
+        mTransitions.unregisterObserver(this);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IHomeTransitionListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IHomeTransitionListener.aidl
new file mode 100644
index 0000000..18716c6
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IHomeTransitionListener.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.window.RemoteTransition;
+import android.window.TransitionFilter;
+
+/**
+ *  Listener interface that Launcher attaches to SystemUI to get home activity transition callbacks.
+ */
+interface IHomeTransitionListener {
+
+    /**
+     * Called when a transition changes the visibility of the home activity.
+     */
+    void onHomeVisibilityChanged(in boolean isVisible);
+}
+
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
index cc4d268..644a6a5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
@@ -19,6 +19,8 @@
 import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 
+import com.android.wm.shell.transition.IHomeTransitionListener;
+
 /**
  * Interface that is exposed to remote callers to manipulate the transitions feature.
  */
@@ -39,4 +41,7 @@
      * Retrieves the apply-token used by transactions in Shell
      */
     IBinder getShellApplyToken() = 3;
+
+    /** Set listener that will receive callbacks about transitions involving home activity */
+    oneway void setHomeTransitionListener(in IHomeTransitionListener listener) = 4;
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 576bba96..baa9aca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -356,7 +356,7 @@
     }
 
     private ExternalInterfaceBinder createExternalInterface() {
-        return new IShellTransitionsImpl(this);
+        return new IShellTransitionsImpl(mContext, getMainExecutor(), this);
     }
 
     @Override
@@ -1400,9 +1400,12 @@
     private static class IShellTransitionsImpl extends IShellTransitions.Stub
             implements ExternalInterfaceBinder {
         private Transitions mTransitions;
+        private final HomeTransitionObserver mHomeTransitionObserver;
 
-        IShellTransitionsImpl(Transitions transitions) {
+        IShellTransitionsImpl(Context context, ShellExecutor executor, Transitions transitions) {
             mTransitions = transitions;
+            mHomeTransitionObserver = new HomeTransitionObserver(context, executor,
+                    mTransitions);
         }
 
         /**
@@ -1410,6 +1413,7 @@
          */
         @Override
         public void invalidate() {
+            mHomeTransitionObserver.invalidate();
             mTransitions = null;
         }
 
@@ -1434,6 +1438,14 @@
         public IBinder getShellApplyToken() {
             return SurfaceControl.Transaction.getDefaultApplyToken();
         }
+
+        @Override
+        public void setHomeTransitionListener(IHomeTransitionListener listener) {
+            executeRemoteCallWithTaskPermission(mTransitions, "setHomeTransitionListener",
+                    (transitions) -> {
+                        mHomeTransitionObserver.setHomeTransitionListener(listener);
+                    });
+        }
     }
 
     private class SettingsObserver extends ContentObserver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 248e837..bb262d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -116,7 +116,8 @@
         this (context, displayController, taskOrganizer, taskInfo, taskSurface, windowDecorConfig,
                 handler, choreographer, syncQueue, rootTaskDisplayAreaOrganizer,
                 SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
-                WindowContainerTransaction::new, new SurfaceControlViewHostFactory() {});
+                WindowContainerTransaction::new, SurfaceControl::new,
+                new SurfaceControlViewHostFactory() {});
     }
 
     DesktopModeWindowDecoration(
@@ -133,10 +134,12 @@
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
             Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
+            Supplier<SurfaceControl> surfaceControlSupplier,
             SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
         super(context, displayController, taskOrganizer, taskInfo, taskSurface, windowDecorConfig,
                 surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
-                windowContainerTransactionSupplier, surfaceControlViewHostFactory);
+                windowContainerTransactionSupplier, surfaceControlSupplier,
+                surfaceControlViewHostFactory);
 
         mHandler = handler;
         mChoreographer = choreographer;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index d0e647b..044c033 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowInsets.Type.statusBars;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration.WindowingMode;
 import android.content.Context;
@@ -137,7 +138,8 @@
             Configuration windowDecorConfig) {
         this(context, displayController, taskOrganizer, taskInfo, taskSurface, windowDecorConfig,
                 SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
-                WindowContainerTransaction::new, new SurfaceControlViewHostFactory() {});
+                WindowContainerTransaction::new, SurfaceControl::new,
+                new SurfaceControlViewHostFactory() {});
     }
 
     WindowDecoration(
@@ -145,17 +147,18 @@
             DisplayController displayController,
             ShellTaskOrganizer taskOrganizer,
             RunningTaskInfo taskInfo,
-            SurfaceControl taskSurface,
+            @NonNull SurfaceControl taskSurface,
             Configuration windowDecorConfig,
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
             Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
+            Supplier<SurfaceControl> surfaceControlSupplier,
             SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
         mContext = context;
         mDisplayController = displayController;
         mTaskOrganizer = taskOrganizer;
         mTaskInfo = taskInfo;
-        mTaskSurface = taskSurface;
+        mTaskSurface = cloneSurfaceControl(taskSurface, surfaceControlSupplier);
         mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
         mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
         mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
@@ -453,6 +456,7 @@
     public void close() {
         mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
         releaseViews();
+        mTaskSurface.release();
     }
 
     static int loadDimensionPixelSize(Resources resources, int resourceId) {
@@ -469,6 +473,13 @@
         return resources.getDimension(resourceId);
     }
 
+    private static SurfaceControl cloneSurfaceControl(SurfaceControl sc,
+            Supplier<SurfaceControl> surfaceControlSupplier) {
+        final SurfaceControl copy = surfaceControlSupplier.get();
+        copy.copyFrom(sc, "WindowDecoration");
+        return copy;
+    }
+
     /**
      * Create a window associated with this WindowDecoration.
      * Note that subclass must dispose of this when the task is hidden/closed.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
index 2cd08a4a..5965805 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt
@@ -26,6 +26,7 @@
 import android.tools.device.flicker.legacy.LegacyFlickerTest
 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
 import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -66,8 +67,10 @@
             standardAppHelper.launchViaIntent(
                 wmHelper,
                 NetflixAppHelper.getNetflixWatchVideoIntent("70184207"),
-                ComponentNameMatcher(NetflixAppHelper.PACKAGE_NAME,
-                    NetflixAppHelper.WATCH_ACTIVITY)
+                ComponentNameMatcher(
+                    NetflixAppHelper.PACKAGE_NAME,
+                    NetflixAppHelper.WATCH_ACTIVITY
+                )
             )
             standardAppHelper.waitForVideoPlaying()
         }
@@ -99,6 +102,41 @@
         super.focusChanges()
     }
 
+    @Postsubmit
+    @Test
+    override fun taskBarLayerIsVisibleAtStartAndEnd() {
+        Assume.assumeTrue(flicker.scenario.isTablet)
+        // Netflix starts in immersive fullscreen mode, so taskbar bar is not visible at start
+        flicker.assertLayersStart { this.isInvisible(ComponentNameMatcher.TASK_BAR) }
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
+    }
+
+    @Postsubmit
+    @Test
+    override fun taskBarWindowIsAlwaysVisible() {
+        // Netflix plays in immersive fullscreen mode, so taskbar will be gone at some point
+    }
+
+    @Postsubmit
+    @Test
+    override fun statusBarLayerIsVisibleAtStartAndEnd() {
+        // Netflix starts in immersive fullscreen mode, so status bar is not visible at start
+        flicker.assertLayersStart { this.isInvisible(ComponentNameMatcher.STATUS_BAR) }
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+    }
+
+    @Postsubmit
+    @Test
+    override fun statusBarLayerPositionAtStartAndEnd() {
+        // Netflix starts in immersive fullscreen mode, so status bar is not visible at start
+        flicker.statusBarLayerPositionAtEnd()
+    }
+
+    @Postsubmit
+    @Test override fun statusBarWindowIsAlwaysVisible() {
+        // Netflix plays in immersive fullscreen mode, so taskbar will be gone at some point
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index e7d0f60..d6141cf 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -568,8 +568,12 @@
     }
 
     private void registerAnimation(int type) {
-        mController.registerAnimation(type,
-                new BackAnimationRunner(mAnimatorCallback, mBackAnimationRunner));
+        mController.registerAnimation(
+                type,
+                new BackAnimationRunner(
+                        mAnimatorCallback,
+                        mBackAnimationRunner,
+                        mContext));
     }
 
     private void unregisterAnimation(int type) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index a2dbab1..18fcdd0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -111,7 +111,8 @@
                 mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl, mConfiguration,
                 mMockHandler, mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer,
                 SurfaceControl.Builder::new, mMockTransactionSupplier,
-                WindowContainerTransaction::new, mMockSurfaceControlViewHostFactory);
+                WindowContainerTransaction::new, SurfaceControl::new,
+                mMockSurfaceControlViewHostFactory);
     }
 
     private ActivityManager.RunningTaskInfo createTaskInfo(boolean visible) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 8061aa3..8e42f74 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -121,6 +121,8 @@
     private WindowContainerTransaction mMockWindowContainerTransaction;
     @Mock
     private SurfaceSyncGroup mMockSurfaceSyncGroup;
+    @Mock
+    private SurfaceControl mMockTaskSurface;
 
     private final List<SurfaceControl.Transaction> mMockSurfaceControlTransactions =
             new ArrayList<>();
@@ -189,8 +191,7 @@
         // Density is 2. Shadow radius is 10px. Caption height is 64px.
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
 
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
@@ -199,7 +200,7 @@
         verify(captionContainerSurfaceBuilder, never()).build();
         verify(mMockSurfaceControlViewHostFactory, never()).create(any(), any(), any());
 
-        verify(mMockSurfaceControlFinishT).hide(taskSurface);
+        verify(mMockSurfaceControlFinishT).hide(mMockTaskSurface);
 
         assertNull(mRelayoutResult.mRootView);
     }
@@ -229,12 +230,11 @@
         taskInfo.isFocused = true;
         // Density is 2. Shadow radius is 10px. Caption height is 64px.
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
-        verify(decorContainerSurfaceBuilder).setParent(taskSurface);
+        verify(decorContainerSurfaceBuilder).setParent(mMockTaskSurface);
         verify(decorContainerSurfaceBuilder).setContainerLayer();
         verify(mMockSurfaceControlStartT).setTrustedOverlay(decorContainerSurface, true);
         verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 300, 100);
@@ -262,14 +262,15 @@
         }
 
         verify(mMockSurfaceControlFinishT)
-                .setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
+                .setPosition(mMockTaskSurface, TASK_POSITION_IN_PARENT.x,
+                        TASK_POSITION_IN_PARENT.y);
         verify(mMockSurfaceControlFinishT)
-                .setWindowCrop(taskSurface, 300, 100);
-        verify(mMockSurfaceControlStartT).setCornerRadius(taskSurface, CORNER_RADIUS);
-        verify(mMockSurfaceControlFinishT).setCornerRadius(taskSurface, CORNER_RADIUS);
+                .setWindowCrop(mMockTaskSurface, 300, 100);
+        verify(mMockSurfaceControlStartT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
+        verify(mMockSurfaceControlFinishT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
         verify(mMockSurfaceControlStartT)
-                .show(taskSurface);
-        verify(mMockSurfaceControlStartT).setShadowRadius(taskSurface, 10);
+                .show(mMockTaskSurface);
+        verify(mMockSurfaceControlStartT).setShadowRadius(mMockTaskSurface, 10);
 
         assertEquals(300, mRelayoutResult.mWidth);
         assertEquals(100, mRelayoutResult.mHeight);
@@ -308,8 +309,7 @@
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
         mWindowConfiguration.densityDpi = taskInfo.configuration.densityDpi;
 
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
@@ -346,8 +346,7 @@
                 .setVisible(true)
                 .build();
 
-        final TestWindowDecoration windowDecor =
-                createWindowDecoration(taskInfo, new SurfaceControl());
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
         windowDecor.relayout(taskInfo);
 
         // It shouldn't show the window decoration when it can't obtain the display instance.
@@ -405,8 +404,7 @@
                 .build();
         taskInfo.isFocused = true;
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
         windowDecor.relayout(taskInfo);
 
         final SurfaceControl additionalWindowSurface = mock(SurfaceControl.class);
@@ -465,8 +463,7 @@
                 .build();
         taskInfo.isFocused = true;
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
@@ -506,8 +503,7 @@
                 .build();
         taskInfo.isFocused = true;
         taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo, true /* applyStartTransactionOnDraw */);
 
@@ -545,12 +541,11 @@
                 .setWindowingMode(WINDOWING_MODE_FREEFORM)
                 .build();
         taskInfo.isFocused = true;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
-        verify(mMockSurfaceControlStartT).setColor(taskSurface, new float[]{1.f, 1.f, 0.f});
+        verify(mMockSurfaceControlStartT).setColor(mMockTaskSurface, new float[]{1.f, 1.f, 0.f});
 
         mockitoSession.finishMocking();
     }
@@ -568,8 +563,7 @@
                 .setTaskDescriptionBuilder(taskDescriptionBuilder)
                 .setVisible(true)
                 .build();
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         assertTrue(mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, statusBars())
                 .isVisible());
@@ -613,12 +607,11 @@
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                 .build();
         taskInfo.isFocused = true;
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
-        verify(mMockSurfaceControlStartT).unsetColor(taskSurface);
+        verify(mMockSurfaceControlStartT).unsetColor(mMockTaskSurface);
 
         mockitoSession.finishMocking();
     }
@@ -639,8 +632,7 @@
                 .setTaskDescriptionBuilder(taskDescriptionBuilder)
                 .setVisible(true)
                 .build();
-        final SurfaceControl taskSurface = mock(SurfaceControl.class);
-        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
 
         windowDecor.relayout(taskInfo);
 
@@ -650,15 +642,15 @@
                 eq(0) /* index */, eq(mandatorySystemGestures()));
     }
 
-    private TestWindowDecoration createWindowDecoration(
-            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
+    private TestWindowDecoration createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo) {
         return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
-                taskInfo, testSurface, mWindowConfiguration,
+                taskInfo, mMockTaskSurface, mWindowConfiguration,
                 new MockObjectSupplier<>(mMockSurfaceControlBuilders,
                         () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
                 new MockObjectSupplier<>(mMockSurfaceControlTransactions,
                         () -> mock(SurfaceControl.Transaction.class)),
-                () -> mMockWindowContainerTransaction, mMockSurfaceControlViewHostFactory);
+                () -> mMockWindowContainerTransaction, () -> mMockTaskSurface,
+                mMockSurfaceControlViewHostFactory);
     }
 
     private class MockObjectSupplier<T> implements Supplier<T> {
@@ -697,11 +689,12 @@
                 Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
                 Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
                 Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
+                Supplier<SurfaceControl> surfaceControlSupplier,
                 SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
             super(context, displayController, taskOrganizer, taskInfo, taskSurface,
                     windowConfiguration, surfaceControlBuilderSupplier,
                     surfaceControlTransactionSupplier, windowContainerTransactionSupplier,
-                    surfaceControlViewHostFactory);
+                    surfaceControlSupplier, surfaceControlViewHostFactory);
         }
 
         @Override
diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig
index e672b98..e986c38 100644
--- a/libs/hwui/aconfig/hwui_flags.aconfig
+++ b/libs/hwui/aconfig/hwui_flags.aconfig
@@ -27,3 +27,10 @@
   description: "APIs to create a new gainmap with a bitmap for metadata."
   bug: "304478551"
 }
+
+flag {
+  name: "clip_surfaceviews"
+  namespace: "core_graphics"
+  description: "Clip z-above surfaceviews to global clip rect"
+  bug: "298621623"
+}
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
index 1042703..814b682 100644
--- a/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
@@ -32,13 +32,13 @@
         , mTotalSize("bytes", 0)
         , mPurgeableSize("bytes", 0) {}
 
-const char* SkiaMemoryTracer::mapName(const char* resourceName) {
+std::optional<std::string> SkiaMemoryTracer::mapName(const std::string& resourceName) {
     for (auto& resource : mResourceMap) {
-        if (SkStrContains(resourceName, resource.first)) {
+        if (resourceName.find(resource.first) != std::string::npos) {
             return resource.second;
         }
     }
-    return nullptr;
+    return std::nullopt;
 }
 
 void SkiaMemoryTracer::processElement() {
@@ -62,7 +62,7 @@
         }
 
         // find the type if one exists
-        const char* type;
+        std::string type;
         auto typeResult = mCurrentValues.find("type");
         if (typeResult != mCurrentValues.end()) {
             type = typeResult->second.units;
@@ -71,14 +71,13 @@
         }
 
         // compute the type if we are itemizing or use the default "size" if we are not
-        const char* key = (mItemizeType) ? type : sizeResult->first;
-        SkASSERT(key != nullptr);
+        std::string key = (mItemizeType) ? type : sizeResult->first;
 
         // compute the top level element name using either the map or category key
-        const char* resourceName = mapName(mCurrentElement.c_str());
-        if (mCategoryKey != nullptr) {
+        std::optional<std::string> resourceName = mapName(mCurrentElement);
+        if (mCategoryKey) {
             // find the category if one exists
-            auto categoryResult = mCurrentValues.find(mCategoryKey);
+            auto categoryResult = mCurrentValues.find(*mCategoryKey);
             if (categoryResult != mCurrentValues.end()) {
                 resourceName = categoryResult->second.units;
             } else if (mItemizeType) {
@@ -87,11 +86,11 @@
         }
 
         // if we don't have a pretty name then use the dumpName
-        if (resourceName == nullptr) {
-            resourceName = mCurrentElement.c_str();
+        if (!resourceName) {
+            resourceName = mCurrentElement;
         }
 
-        auto result = mResults.find(resourceName);
+        auto result = mResults.find(*resourceName);
         if (result != mResults.end()) {
             auto& resourceValues = result->second;
             typeResult = resourceValues.find(key);
@@ -106,7 +105,7 @@
             TraceValue sizeValue = sizeResult->second;
             mCurrentValues.clear();
             mCurrentValues.insert({key, sizeValue});
-            mResults.insert({resourceName, mCurrentValues});
+            mResults.insert({*resourceName, mCurrentValues});
         }
     }
 
@@ -139,8 +138,9 @@
             for (const auto& typedValue : namedItem.second) {
                 TraceValue traceValue = convertUnits(typedValue.second);
                 const char* entry = (traceValue.count > 1) ? "entries" : "entry";
-                log.appendFormat("    %s: %.2f %s (%d %s)\n", typedValue.first, traceValue.value,
-                                 traceValue.units, traceValue.count, entry);
+                log.appendFormat("    %s: %.2f %s (%d %s)\n", typedValue.first.c_str(),
+                                 traceValue.value, traceValue.units.c_str(), traceValue.count,
+                                 entry);
             }
         } else {
             auto result = namedItem.second.find("size");
@@ -148,7 +148,8 @@
                 TraceValue traceValue = convertUnits(result->second);
                 const char* entry = (traceValue.count > 1) ? "entries" : "entry";
                 log.appendFormat("  %s: %.2f %s (%d %s)\n", namedItem.first.c_str(),
-                                 traceValue.value, traceValue.units, traceValue.count, entry);
+                                 traceValue.value, traceValue.units.c_str(), traceValue.count,
+                                 entry);
             }
         }
     }
@@ -156,7 +157,7 @@
 
 size_t SkiaMemoryTracer::total() {
     processElement();
-    if (!strcmp("bytes", mTotalSize.units)) {
+    if ("bytes" == mTotalSize.units) {
         return mTotalSize.value;
     }
     return 0;
@@ -166,16 +167,16 @@
     TraceValue total = convertUnits(mTotalSize);
     TraceValue purgeable = convertUnits(mPurgeableSize);
     log.appendFormat("  %.0f bytes, %.2f %s (%.2f %s is purgeable)\n", mTotalSize.value,
-                     total.value, total.units, purgeable.value, purgeable.units);
+                     total.value, total.units.c_str(), purgeable.value, purgeable.units.c_str());
 }
 
 SkiaMemoryTracer::TraceValue SkiaMemoryTracer::convertUnits(const TraceValue& value) {
     TraceValue output(value);
-    if (SkString("bytes") == SkString(output.units) && output.value >= 1024) {
+    if ("bytes" == output.units && output.value >= 1024) {
         output.value = output.value / 1024.0f;
         output.units = "KB";
     }
-    if (SkString("KB") == SkString(output.units) && output.value >= 1024) {
+    if ("KB" == output.units && output.value >= 1024) {
         output.value = output.value / 1024.0f;
         output.units = "MB";
     }
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.h b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
index cba3b04..dbfc86b 100644
--- a/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
@@ -16,8 +16,9 @@
 
 #pragma once
 
-#include <SkString.h>
 #include <SkTraceMemoryDump.h>
+#include <optional>
+#include <string>
 #include <utils/String8.h>
 #include <unordered_map>
 #include <vector>
@@ -60,17 +61,17 @@
         TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
         TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
 
-        const char* units;
+        std::string units;
         float value;
         int count;
     };
 
-    const char* mapName(const char* resourceName);
+    std::optional<std::string> mapName(const std::string& resourceName);
     void processElement();
     TraceValue convertUnits(const TraceValue& value);
 
     const std::vector<ResourcePair> mResourceMap;
-    const char* mCategoryKey = nullptr;
+    std::optional<std::string> mCategoryKey;
     const bool mItemizeType;
 
     // variables storing the size of all elements being dumped
@@ -79,12 +80,12 @@
 
     // variables storing information on the current node being dumped
     std::string mCurrentElement;
-    std::unordered_map<const char*, TraceValue> mCurrentValues;
+    std::unordered_map<std::string, TraceValue> mCurrentValues;
 
     // variable that stores the final format of the data after the individual elements are processed
-    std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
+    std::unordered_map<std::string, std::unordered_map<std::string, TraceValue>> mResults;
 };
 
 } /* namespace skiapipeline */
 } /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 14602ef..7fac0c9 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -562,7 +562,11 @@
 void CanvasContext::draw(bool solelyTextureViewUpdates) {
     if (auto grContext = getGrContext()) {
         if (grContext->abandoned()) {
-            LOG_ALWAYS_FATAL("GrContext is abandoned/device lost at start of CanvasContext::draw");
+            if (grContext->isDeviceLost()) {
+                LOG_ALWAYS_FATAL("Lost GPU device unexpectedly");
+                return;
+            }
+            LOG_ALWAYS_FATAL("GrContext is abandoned at start of CanvasContext::draw");
             return;
         }
     }
diff --git a/location/api/current.txt b/location/api/current.txt
index 33effdd..0c23d8c 100644
--- a/location/api/current.txt
+++ b/location/api/current.txt
@@ -412,7 +412,9 @@
     field public static final int TYPE_GPS_L1CA = 257; // 0x101
     field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
     field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final int TYPE_IRN_L5CA = 1793; // 0x701
+    field @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1) public static final int TYPE_IRN_L1 = 1795; // 0x703
+    field @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1) public static final int TYPE_IRN_L5 = 1794; // 0x702
+    field @Deprecated public static final int TYPE_IRN_L5CA = 1793; // 0x701
     field public static final int TYPE_QZS_L1CA = 1025; // 0x401
     field public static final int TYPE_SBS = 513; // 0x201
     field public static final int TYPE_UNKNOWN = 0; // 0x0
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index 637f905..32e636f 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -16,10 +16,12 @@
 
 package android.location;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.location.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,7 +43,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
             TYPE_SBS, TYPE_GLO_L1CA, TYPE_QZS_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_BDS_CNAV1,
-            TYPE_BDS_CNAV2, TYPE_GAL_I, TYPE_GAL_F, TYPE_IRN_L5CA})
+            TYPE_BDS_CNAV2, TYPE_GAL_I, TYPE_GAL_F, TYPE_IRN_L5CA, TYPE_IRN_L5, TYPE_IRN_L1})
     public @interface GnssNavigationMessageType {}
 
     // The following enumerations must be in sync with the values declared in gps.h
@@ -74,8 +76,18 @@
     public static final int TYPE_GAL_I = 0x0601;
     /** Galileo F/NAV message contained in the structure. */
     public static final int TYPE_GAL_F = 0x0602;
-    /** IRNSS L5 C/A message contained in the structure. */
+    /**
+     * NavIC L5 C/A message contained in the structure.
+     * @deprecated Use {@link #TYPE_IRN_L5} instead.
+     */
+    @Deprecated
     public static final int TYPE_IRN_L5CA = 0x0701;
+    /** NavIC L5 message contained in the structure. */
+    @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1)
+    public static final int TYPE_IRN_L5 = 0x0702;
+    /** NavIC L1 message contained in the structure. */
+    @FlaggedApi(Flags.FLAG_GNSS_API_NAVIC_L1)
+    public static final int TYPE_IRN_L1 = 0x0703;
 
     /**
      * The status of the GNSS Navigation Message
@@ -254,8 +266,15 @@
             case TYPE_GAL_F:
                 return "Galileo F";
             case TYPE_IRN_L5CA:
-                return "IRNSS L5 C/A";
+                return "NavIC L5 C/A";
             default:
+                if (Flags.gnssApiNavicL1()) {
+                    if (mType == TYPE_IRN_L5) {
+                        return "NavIC L5";
+                    } else if (mType == TYPE_IRN_L1) {
+                        return "NavIC L1";
+                    }
+                }
                 return "<Invalid:" + mType + ">";
         }
     }
@@ -303,9 +322,12 @@
      * navigation message, in the range of 1-25 (Subframe 1, 2, 3 does not contain a 'frame id' and
      * this value can be set to -1.)</li>
      * <li> For Beidou CNAV1 this refers to the page type number in the range of 1-63.</li>
-     * <li> For IRNSS L5 C/A subframe 3 and 4, this value corresponds to the Message Id of the
+     * <li> For NavIC L5 subframe 3 and 4, this value corresponds to the Message Id of the
      * navigation message, in the range of 1-63. (Subframe 1 and 2 does not contain a message type
      * id and this value can be set to -1.)</li>
+     * <li> For NavIC L1 subframe 3, this value corresponds to the Message Id of the navigation
+     * message, in the range of 1-63. (Subframe 1 and 2 does not contain a message type id and this
+     * value can be set to -1.)</li>
      * </ul>
      */
     @IntRange(from = -1, to = 120)
@@ -339,8 +361,10 @@
      * navigation message, in the range of 1-3.</li>
      * <li> For Beidou CNAV2, the submessage id corresponds to the message type, in the range
      * 1-63.</li>
-     * <li> For IRNSS L5 C/A, the submessage id corresponds to the subframe number of the
-     * navigation message, in the range of 1-4.</li>
+     * <li> For NavIC L5, the submessage id corresponds to the subframe number of the navigation
+     * message, in the range of 1-4.</li>
+     * <li> For NavIC L1, the submessage id corresponds to the subframe number of the navigation
+     * message, in the range of 1-3.</li>
      * </ul>
      */
     @IntRange(from = 1)
@@ -363,7 +387,7 @@
      * <p>The bytes (or words) specified using big endian format (MSB first).
      *
      * <ul>
-     * <li>For GPS L1 C/A, IRNSS L5 C/A, Beidou D1 &amp; Beidou D2, each subframe contains 10
+     * <li>For GPS L1 C/A, NavIC L5, Beidou D1 &amp; Beidou D2, each subframe contains 10
      * 30-bit words. Each word (30 bits) should be fit into the last 30 bits in a 4-byte word (skip
      * B31 and B32), with MSB first, for a total of 40 bytes, covering a time period of 6, 6, and
      * 0.6 seconds, respectively.</li>
@@ -383,6 +407,9 @@
      * 75 bytes. subframe #3 consists of 264 data bits that should be fit into 33 bytes.</li>
      * <li>For Beidou CNAV2, each subframe consists of 288 data bits, that should be fit into 36
      * bytes.</li>
+     * <li> For NavIC L1, subframe #1 consists of 9 data bits that should be fit into 2 bytes (skip
+     * B10-B16). subframe #2 consists of 600 bits that should be fit into 75 bytes. subframe #3
+     * consists of 274 data bits that should be fit into 35 bytes (skip B275-B280).</li>
      * </ul>
      */
     @NonNull
diff --git a/location/java/android/location/flags/gnss.aconfig b/location/java/android/location/flags/gnss.aconfig
new file mode 100644
index 0000000..c471a27
--- /dev/null
+++ b/location/java/android/location/flags/gnss.aconfig
@@ -0,0 +1,8 @@
+package: "android.location.flags"
+
+flag {
+    name: "gnss_api_navic_l1"
+    namespace: "location"
+    description: "Flag for GNSS API for NavIC L1"
+    bug: "302199306"
+}
\ No newline at end of file
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 76a00ac..f68eb3d 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -52,6 +52,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -383,9 +384,9 @@
      * @see #setRouteListingPreference(RouteListingPreference)
      */
     @FlaggedApi(FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2)
-    public void registerRouteListingPreferenceCallback(
+    public void registerRouteListingPreferenceUpdatedCallback(
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull RouteListingPreferenceCallback routeListingPreferenceCallback) {
+            @NonNull Consumer<RouteListingPreference> routeListingPreferenceCallback) {
         Objects.requireNonNull(executor, "executor must not be null");
         Objects.requireNonNull(routeListingPreferenceCallback, "callback must not be null");
 
@@ -398,15 +399,20 @@
 
     /**
      * Unregisters the given callback to not receive {@link RouteListingPreference} change events.
+     *
+     * @see #registerRouteListingPreferenceUpdatedCallback(Executor, Consumer)
      */
     @FlaggedApi(FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2)
-    public void unregisterRouteListingPreferenceCallback(
-            @NonNull RouteListingPreferenceCallback callback) {
+    public void unregisterRouteListingPreferenceUpdatedCallback(
+            @NonNull Consumer<RouteListingPreference> callback) {
         Objects.requireNonNull(callback, "callback must not be null");
 
         if (!mListingPreferenceCallbackRecords.remove(
                 new RouteListingPreferenceCallbackRecord(/* executor */ null, callback))) {
-            Log.w(TAG, "unregisterRouteListingPreferenceCallback: Ignoring an unknown callback");
+            Log.w(
+                    TAG,
+                    "unregisterRouteListingPreferenceUpdatedCallback: Ignoring an unknown"
+                        + " callback");
         }
     }
 
@@ -1119,9 +1125,7 @@
     private void notifyRouteListingPreferenceUpdated(@Nullable RouteListingPreference preference) {
         for (RouteListingPreferenceCallbackRecord record : mListingPreferenceCallbackRecords) {
             record.mExecutor.execute(
-                    () ->
-                            record.mRouteListingPreferenceCallback.onRouteListingPreferenceChanged(
-                                    preference));
+                    () -> record.mRouteListingPreferenceCallback.accept(preference));
         }
     }
 
@@ -1208,22 +1212,6 @@
         public void onPreferredFeaturesChanged(@NonNull List<String> preferredFeatures) {}
     }
 
-    /** Callback for receiving events related to {@link RouteListingPreference}. */
-    @FlaggedApi(FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2)
-    public abstract static class RouteListingPreferenceCallback {
-
-        @FlaggedApi(FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2)
-        public RouteListingPreferenceCallback() {}
-
-        /**
-         * Called when the {@link RouteListingPreference} changes.
-         *
-         * @see #getRouteListingPreference
-         */
-        @FlaggedApi(FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2)
-        public void onRouteListingPreferenceChanged(@Nullable RouteListingPreference preference) {}
-    }
-
     /** Callback for receiving events on media transfer. */
     public abstract static class TransferCallback {
         /**
@@ -1774,11 +1762,11 @@
 
     private static final class RouteListingPreferenceCallbackRecord {
         public final Executor mExecutor;
-        public final RouteListingPreferenceCallback mRouteListingPreferenceCallback;
+        public final Consumer<RouteListingPreference> mRouteListingPreferenceCallback;
 
         /* package */ RouteListingPreferenceCallbackRecord(
                 @NonNull Executor executor,
-                @NonNull RouteListingPreferenceCallback routeListingPreferenceCallback) {
+                @NonNull Consumer<RouteListingPreference> routeListingPreferenceCallback) {
             mExecutor = executor;
             mRouteListingPreferenceCallback = routeListingPreferenceCallback;
         }
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index d0e860c..10c880d 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -193,4 +193,30 @@
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MANAGE_MEDIA_PROJECTION)")
     oneway void notifyPermissionRequestInitiated(int hostUid, int sessionCreationSource);
+
+    /**
+     * Notifies system server that the permission request was displayed.
+     *
+     * <p>Only used for emitting atoms.
+     *
+     * @param hostUid The uid of the process requesting consent to capture, may be an app or
+     *                SystemUI.
+     */
+    @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
+    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+            + ".permission.MANAGE_MEDIA_PROJECTION)")
+    oneway void notifyPermissionRequestDisplayed(int hostUid);
+
+    /**
+     * Notifies system server that the app selector was displayed.
+     *
+     * <p>Only used for emitting atoms.
+     *
+     * @param hostUid The uid of the process requesting consent to capture, may be an app or
+     *                SystemUI.
+     */
+    @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
+    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+            + ".permission.MANAGE_MEDIA_PROJECTION)")
+    oneway void notifyAppSelectorDisplayed(int hostUid);
 }
diff --git a/nfc-extras/OWNERS b/nfc-extras/OWNERS
new file mode 100644
index 0000000..35e9713
--- /dev/null
+++ b/nfc-extras/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48448
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index ffed804..fe8386e 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -16,6 +16,8 @@
 
 package com.android.nfc_extras;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.HashMap;
 
 import android.content.Context;
@@ -30,6 +32,8 @@
  *
  * There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
  * a {@link NfcAdapter} object.
+ *
+ * TODO(b/303286040): Deprecate this API surface since this is no longer supported (see ag/443092)
  */
 public final class NfcAdapterExtras {
     private static final String TAG = "NfcAdapterExtras";
@@ -72,15 +76,40 @@
     private final NfcAdapter mAdapter;
     final String mPackageName;
 
+    private static INfcAdapterExtras
+        getNfcAdapterExtrasInterfaceFromNfcAdapter(NfcAdapter adapter) {
+        try {
+            Method method = NfcAdapter.class.getDeclaredMethod("getNfcAdapterExtrasInterface");
+            method.setAccessible(true);
+            return (INfcAdapterExtras) method.invoke(adapter);
+        } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+                 | IllegalAccessException | IllegalAccessError | InvocationTargetException e) {
+            Log.e(TAG, "Unable to get context from NfcAdapter");
+        }
+        return null;
+    }
+
     /** get service handles */
     private static void initService(NfcAdapter adapter) {
-        final INfcAdapterExtras service = adapter.getNfcAdapterExtrasInterface();
+        final INfcAdapterExtras service = getNfcAdapterExtrasInterfaceFromNfcAdapter(adapter);
         if (service != null) {
             // Leave stale rather than receive a null value.
             sService = service;
         }
     }
 
+    private static Context getContextFromNfcAdapter(NfcAdapter adapter) {
+        try {
+            Method method = NfcAdapter.class.getDeclaredMethod("getContext");
+            method.setAccessible(true);
+            return (Context) method.invoke(adapter);
+        } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+                 | IllegalAccessException | IllegalAccessError | InvocationTargetException e) {
+            Log.e(TAG, "Unable to get context from NfcAdapter");
+        }
+        return null;
+    }
+
     /**
      * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
      *
@@ -91,7 +120,7 @@
      * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
      */
     public static NfcAdapterExtras get(NfcAdapter adapter) {
-        Context context = adapter.getContext();
+        Context context = getContextFromNfcAdapter(adapter);
         if (context == null) {
             throw new UnsupportedOperationException(
                     "You must pass a context to your NfcAdapter to use the NFC extras APIs");
@@ -112,7 +141,7 @@
 
     private NfcAdapterExtras(NfcAdapter adapter) {
         mAdapter = adapter;
-        mPackageName = adapter.getContext().getPackageName();
+        mPackageName = getContextFromNfcAdapter(adapter).getPackageName();
         mEmbeddedEe = new NfcExecutionEnvironment(this);
         mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
                 mEmbeddedEe);
@@ -156,12 +185,24 @@
         }
     }
 
+    private static void attemptDeadServiceRecoveryOnNfcAdapter(NfcAdapter adapter, Exception e) {
+        try {
+            Method method = NfcAdapter.class.getDeclaredMethod(
+                    "attemptDeadServiceRecovery", Exception.class);
+            method.setAccessible(true);
+            method.invoke(adapter, e);
+        } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+                 | IllegalAccessException | IllegalAccessError | InvocationTargetException ex) {
+            Log.e(TAG, "Unable to attempt dead service recovery on NfcAdapter");
+        }
+    }
+
     /**
      * NFC service dead - attempt best effort recovery
      */
     void attemptDeadServiceRecovery(Exception e) {
         Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
-        mAdapter.attemptDeadServiceRecovery(e);
+        attemptDeadServiceRecoveryOnNfcAdapter(mAdapter, e);
         initService(mAdapter);
     }
 
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 30d1773..4e4894c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -27,7 +27,7 @@
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Geçiş anahtarlarıyla daha yüksek güvenlik"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Geçiş anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Geçiş anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
-    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Diğer cihazlarda oturum açabilmeniz için şifre anahtarları bir şifre yöneticisine kaydedilir"</string>
+    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Diğer cihazlarda oturum açabilmeniz için geçiş anahtarları bir şifre yöneticisine kaydedilir"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Geçiş anahtarları hakkında daha fazla bilgi"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Şifresiz teknoloji"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Geçiş anahtarları, şifre kullanmadan oturum açmanıza olanak tanır. Kimliğinizi doğrulayıp geçiş anahtarı oluşturmak için parmak iziniz, yüz tanıma özelliği, PIN veya kaydırma deseni kullanmanız yeterlidir."</string>
@@ -39,10 +39,10 @@
     <string name="seamless_transition_detail" msgid="4475509237171739843">"Şifresiz bir geleceğe doğru ilerlerken şifreler, geçiş anahtarlarıyla birlikte kullanılmaya devam edecektir."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> kaydedileceği yeri seçin"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Bilgilerinizi kaydedip bir dahaki sefere daha hızlı oturum açmak için bir şifre yöneticisi seçin"</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre anahtarı oluşturulsun mu?"</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> için geçiş anahtarı oluşturulsun mu?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre kaydedilsin mi?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> için oturum açma bilgileri kaydedilsin mi?"</string>
-    <string name="passkey" msgid="632353688396759522">"Şifre anahtarı"</string>
+    <string name="passkey" msgid="632353688396759522">"Geçiş anahtarı"</string>
     <string name="password" msgid="6738570945182936667">"Şifre"</string>
     <string name="passkeys" msgid="5733880786866559847">"Geçiş anahtarlarınızın"</string>
     <string name="passwords" msgid="5419394230391253816">"şifreler"</string>
@@ -61,14 +61,14 @@
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> geçiş anahtarı"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> kimlik bilgileri"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Şifre anahtarı"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Geçiş anahtarı"</string>
     <string name="another_device" msgid="5147276802037801217">"Başka bir cihaz"</string>
     <string name="other_password_manager" msgid="565790221427004141">"Diğer şifre yöneticileri"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sayfayı kapat"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
     <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Kapat"</string>
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifre anahtarınız kullanılsın mı?"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı geçiş anahtarınız kullanılsın mı?"</string>
     <string name="get_dialog_title_use_password_for" msgid="625828023234318484">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifreniz kullanılsın mı?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma bilgileriniz kullanılsın mı?"</string>
     <string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma seçeneklerine izin verilsin mi?"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index 222b865..495abe6 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -53,7 +53,7 @@
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"在其他设备上保存密码?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"在其他设备上保存登录凭据?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"将“<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>”用于您的所有登录信息?"</string>
-    <string name="use_provider_for_all_description" msgid="1998772715863958997">"此 <xliff:g id="USERNAME">%1$s</xliff:g> 密码管理工具将会存储您的密码和通行密钥,帮助您轻松登录"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> 的这个密码管理工具将会存储您的密码和通行密钥,帮助您轻松登录"</string>
     <string name="set_as_default" msgid="4415328591568654603">"设为默认项"</string>
     <string name="settings" msgid="6536394145760913145">"设置"</string>
     <string name="use_once" msgid="9027366575315399714">"使用一次"</string>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index 9355517..d35dcb5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -43,6 +43,9 @@
 import android.widget.inline.InlinePresentationSpec
 import androidx.autofill.inline.v1.InlineSuggestionUi
 import com.android.credentialmanager.GetFlowUtils
+import com.android.credentialmanager.getflow.CredentialEntryInfo
+import com.android.credentialmanager.getflow.ProviderDisplayInfo
+import com.android.credentialmanager.getflow.toProviderDisplayInfo
 import org.json.JSONObject
 import java.util.concurrent.Executors
 
@@ -114,10 +117,14 @@
         val providerList = GetFlowUtils.toProviderList(
                 getCredResponse.candidateProviderDataList,
                 this@CredentialAutofillService)
+        if (providerList.isEmpty()) {
+            return null
+        }
         var totalEntryCount = 0
         providerList.forEach { provider ->
             totalEntryCount += provider.credentialEntryList.size
         }
+        val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerList)
         val inlineSuggestionsRequest = filLRequest.inlineSuggestionsRequest
         val inlineMaxSuggestedCount = inlineSuggestionsRequest?.maxSuggestionCount ?: 0
         val inlinePresentationSpecs = inlineSuggestionsRequest?.inlinePresentationSpecs
@@ -129,15 +136,30 @@
         var i = 0
         val fillResponseBuilder = FillResponse.Builder()
         var emptyFillResponse = true
-        providerList.forEach {provider ->
-            // TODO(b/299321128): Before iterating the list, sort the list so that
-            //  the relevant entries don't get truncated
-            provider.credentialEntryList.forEach entryLoop@ {entry ->
-                val autofillId: AutofillId? = entry.fillInIntent?.getParcelableExtra(
-                        CredentialProviderService.EXTRA_AUTOFILL_ID,
-                        AutofillId::class.java)
-                val pendingIntent = entry.pendingIntent
+
+        providerDisplayInfo.sortedUserNameToCredentialEntryList.forEach usernameLoop@ {
+            val primaryEntry = it.sortedCredentialEntryList.first()
+            // In regular CredMan bottomsheet, only one primary entry per username is displayed.
+            // But since the credential requests from different fields are allocated into a single
+            // request for autofill, there will be duplicate primary entries, especially for
+            // username/pw autofill fields. These primary entries will be the same entries except
+            // their autofillIds will point to different autofill fields. Process all primary
+            // fields.
+            // TODO(b/307435163): Merge credential options
+            it.sortedCredentialEntryList.forEach entryLoop@ { credentialEntry ->
+                if (!isSameCredentialEntry(primaryEntry, credentialEntry)) {
+                    // Encountering different credential entry means all the duplicate primary
+                    // entries have been processed.
+                    return@usernameLoop
+                }
+                val autofillId: AutofillId? = credentialEntry
+                        .fillInIntent
+                        ?.getParcelableExtra(
+                                CredentialProviderService.EXTRA_AUTOFILL_ID,
+                                AutofillId::class.java)
+                val pendingIntent = credentialEntry.pendingIntent
                 if (autofillId == null || pendingIntent == null) {
+                    Log.e(TAG, "AutofillId or pendingIntent was missing from the entry.")
                     return@entryLoop
                 }
                 var inlinePresentation: InlinePresentation? = null
@@ -151,7 +173,7 @@
                     }
                     val sliceBuilder = InlineSuggestionUi
                             .newContentBuilder(pendingIntent)
-                            .setTitle(entry.userName)
+                            .setTitle(credentialEntry.userName)
                     inlinePresentation = InlinePresentation(
                             sliceBuilder.build().slice, spec, /* pinned= */ false)
                 }
@@ -169,8 +191,8 @@
                                         Field.Builder().setPresentations(
                                                 presentationBuilder.build())
                                                 .build())
-                                .setAuthentication(entry.pendingIntent.intentSender)
-                                .setAuthenticationExtras(entry.fillInIntent.extras)
+                                .setAuthentication(pendingIntent.intentSender)
+                                .setAuthenticationExtras(credentialEntry.fillInIntent.extras)
                                 .build())
                 emptyFillResponse = false
             }
@@ -292,4 +314,15 @@
         }
         return result
     }
+
+    private fun isSameCredentialEntry(
+            info1: CredentialEntryInfo,
+            info2: CredentialEntryInfo
+    ): Boolean {
+        return info1.providerId == info2.providerId &&
+                info1.lastUsedTimeMillis == info2.lastUsedTimeMillis &&
+                info1.credentialType == info2.credentialType &&
+                info1.displayName == info2.displayName &&
+                info1.userName == info2.userName
+    }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index 716f474..447a9d2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -203,9 +203,14 @@
     UNLOCKED_AUTH_ENTRIES_ONLY,
 }
 
-// IMPORTANT: new invocation should be mindful that this method will throw if more than 1 remote
-// entry exists
-private fun toProviderDisplayInfo(
+
+/**
+ * IMPORTANT: new invocation should be mindful that this method will throw if more than 1 remote
+ * entry exists
+ *
+ * @hide
+ */
+fun toProviderDisplayInfo(
     providerInfoList: List<ProviderInfo>
 ): ProviderDisplayInfo {
     val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
diff --git a/packages/SettingsLib/AppPreference/res/layout-v33/preference_app.xml b/packages/SettingsLib/AppPreference/res/layout-v33/preference_app.xml
index 8975857..47ce587 100644
--- a/packages/SettingsLib/AppPreference/res/layout-v33/preference_app.xml
+++ b/packages/SettingsLib/AppPreference/res/layout-v33/preference_app.xml
@@ -83,7 +83,7 @@
             android:id="@android:id/progress"
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_height="4dp"
             android:layout_marginTop="4dp"
             android:max="100"
             android:visibility="gone"/>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
index f1e028b..6979825 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/style_preference.xml
@@ -25,6 +25,7 @@
         <item name="editTextPreferenceStyle">@style/SettingsEditTextPreference.SettingsLib</item>
         <item name="dropdownPreferenceStyle">@style/SettingsDropdownPreference.SettingsLib</item>
         <item name="switchPreferenceStyle">@style/SettingsSwitchPreference.SettingsLib</item>
+        <item name="switchPreferenceCompatStyle">@style/SettingsSwitchPreferenceCompat.SettingsLib</item>
         <item name="seekBarPreferenceStyle">@style/SettingsSeekbarPreference.SettingsLib</item>
         <item name="footerPreferenceStyle">@style/Preference.Material</item>
     </style>
@@ -67,6 +68,11 @@
         <item name="iconSpaceReserved">@bool/settingslib_config_icon_space_reserved</item>
     </style>
 
+    <style name="SettingsSwitchPreferenceCompat.SettingsLib" parent="@style/Preference.SwitchPreferenceCompat.Material">
+        <item name="layout">@layout/settingslib_preference</item>
+        <item name="iconSpaceReserved">@bool/settingslib_config_icon_space_reserved</item>
+    </style>
+
     <style name="SettingsSeekbarPreference.SettingsLib" parent="@style/Preference.SeekBarPreference.Material">
         <item name="iconSpaceReserved">@bool/settingslib_config_icon_space_reserved</item>
     </style>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
index c4b6047..f44b161 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
@@ -34,12 +34,17 @@
     </style>
 
     <style name="Switch.SettingsLib" parent="@android:style/Widget.Material.CompoundButton.Switch">
-        <item name="android:switchMinWidth">52dp</item>
         <item name="android:minHeight">@dimen/settingslib_preferred_minimum_touch_target</item>
         <item name="android:track">@drawable/settingslib_switch_track</item>
         <item name="android:thumb">@drawable/settingslib_switch_thumb</item>
     </style>
 
+    <style name="SwitchCompat.SettingsLib" parent="@style/Widget.AppCompat.CompoundButton.Switch">
+        <item name="android:minHeight">@dimen/settingslib_preferred_minimum_touch_target</item>
+        <item name="track">@drawable/settingslib_switch_track</item>
+        <item name="android:thumb">@drawable/settingslib_switch_thumb</item>
+    </style>
+
     <style name="HorizontalProgressBar.SettingsLib"
            parent="android:style/Widget.Material.ProgressBar.Horizontal">
         <item name="android:progressDrawable">@drawable/settingslib_progress_horizontal</item>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
index 69c122c..698f21d 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
@@ -25,6 +25,7 @@
         <item name="android:listPreferredItemPaddingRight">16dp</item>
         <item name="preferenceTheme">@style/PreferenceTheme.SettingsLib</item>
         <item name="android:switchStyle">@style/Switch.SettingsLib</item>
+        <item name="switchStyle">@style/SwitchCompat.SettingsLib</item>
         <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBar.SettingsLib</item>
     </style>
 
diff --git a/packages/SettingsLib/SpaPrivileged/Android.bp b/packages/SettingsLib/SpaPrivileged/Android.bp
index eaeda3c..009407a 100644
--- a/packages/SettingsLib/SpaPrivileged/Android.bp
+++ b/packages/SettingsLib/SpaPrivileged/Android.bp
@@ -38,6 +38,7 @@
     static_libs: [
         "androidx.compose.runtime_runtime",
         "SpaPrivilegedLib",
+        "android.content.pm.flags-aconfig-java",
     ],
     kotlincflags: ["-Xjvm-default=all"],
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
index a428142..d95dd8c 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListRepository.kt
@@ -17,6 +17,8 @@
 package com.android.settingslib.spaprivileged.model.app
 
 import android.content.Context
+import android.content.pm.FeatureFlags
+import android.content.pm.FeatureFlagsImpl
 import android.content.Intent
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
@@ -65,10 +67,15 @@
         AppListRepositoryImpl(context).getSystemPackageNamesBlocking(userId)
 }
 
-class AppListRepositoryImpl(private val context: Context) : AppListRepository {
+class AppListRepositoryImpl(
+    private val context: Context,
+    private val featureFlags: FeatureFlags
+) : AppListRepository {
     private val packageManager = context.packageManager
     private val userManager = context.userManager
 
+    constructor(context: Context) : this(context, FeatureFlagsImpl())
+
     override suspend fun loadApps(
         userId: Int,
         loadInstantApps: Boolean,
@@ -98,9 +105,13 @@
         userId: Int,
         matchAnyUserForAdmin: Boolean,
     ): List<ApplicationInfo> {
+        val disabledComponentsFlag = (PackageManager.MATCH_DISABLED_COMPONENTS or
+            PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS).toLong()
+        val archivedPackagesFlag: Long = if (featureFlags.archiving())
+            PackageManager.MATCH_ARCHIVED_PACKAGES else 0L
         val regularFlags = ApplicationInfoFlags.of(
-            (PackageManager.MATCH_DISABLED_COMPONENTS or
-                PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS).toLong()
+            disabledComponentsFlag or
+                archivedPackagesFlag
         )
         return if (!matchAnyUserForAdmin || !userManager.getUserInfo(userId).isAdmin) {
             packageManager.getInstalledApplicationsAsUser(regularFlags, userId)
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
index 517f67e..840bca8 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListRepositoryTest.kt
@@ -47,6 +47,8 @@
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
+import android.content.pm.FakeFeatureFlagsImpl
+import android.content.pm.Flags
 
 @RunWith(AndroidJUnit4::class)
 class AppListRepositoryTest {
@@ -268,6 +270,40 @@
     }
 
     @Test
+    fun loadApps_archivedAppsEnabled() = runTest {
+        val fakeFlags = FakeFeatureFlagsImpl()
+        fakeFlags.setFlag(Flags.FLAG_ARCHIVING, true)
+        mockInstalledApplications(listOf(NORMAL_APP, ARCHIVED_APP), ADMIN_USER_ID)
+        val repository = AppListRepositoryImpl(context, fakeFlags)
+        val appList = repository.loadApps(userId = ADMIN_USER_ID)
+
+        assertThat(appList).containsExactly(NORMAL_APP, ARCHIVED_APP)
+        argumentCaptor<ApplicationInfoFlags> {
+            verify(packageManager).getInstalledApplicationsAsUser(capture(), eq(ADMIN_USER_ID))
+            assertThat(firstValue.value).isEqualTo(
+                (PackageManager.MATCH_DISABLED_COMPONENTS or
+                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS).toLong() or
+                    PackageManager.MATCH_ARCHIVED_PACKAGES
+            )
+        }
+    }
+
+    @Test
+    fun loadApps_archivedAppsDisabled() = runTest {
+        mockInstalledApplications(listOf(NORMAL_APP), ADMIN_USER_ID)
+        val appList = repository.loadApps(userId = ADMIN_USER_ID)
+
+        assertThat(appList).containsExactly(NORMAL_APP)
+        argumentCaptor<ApplicationInfoFlags> {
+            verify(packageManager).getInstalledApplicationsAsUser(capture(), eq(ADMIN_USER_ID))
+            assertThat(firstValue.value).isEqualTo(
+                PackageManager.MATCH_DISABLED_COMPONENTS or
+                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+            )
+        }
+    }
+
+    @Test
     fun showSystemPredicate_showSystem() = runTest {
         val app = SYSTEM_APP
 
@@ -391,6 +427,12 @@
             flags = ApplicationInfo.FLAG_SYSTEM
         }
 
+        val ARCHIVED_APP = ApplicationInfo().apply {
+            packageName = "archived.app"
+            flags = ApplicationInfo.FLAG_SYSTEM
+            isArchived = true
+        }
+
         fun resolveInfoOf(packageName: String) = ResolveInfo().apply {
             activityInfo = ActivityInfo().apply {
                 this.packageName = packageName
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index afdb92b..9d986f4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Kies profiel"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoonlik"</string>
     <string name="category_work" msgid="4014193632325996115">"Werk"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privaat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Kloon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Ontwikkelaaropsies"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktiveer ontwikkelaaropsies"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index ea8491b..b4887b9 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"መገለጫ ይምረጡ"</string>
     <string name="category_personal" msgid="6236798763159385225">"የግል"</string>
     <string name="category_work" msgid="4014193632325996115">"ሥራ"</string>
+    <string name="category_private" msgid="4244892185452788977">"የግል"</string>
     <string name="category_clone" msgid="1554511758987195974">"አባዛ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"የገንቢዎች አማራጮች"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"የገንቢዎች አማራጮችን አንቃ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c29e691..b8f92a3 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"اختيار ملف شخصي"</string>
     <string name="category_personal" msgid="6236798763159385225">"التطبيقات الشخصية"</string>
     <string name="category_work" msgid="4014193632325996115">"تطبيقات العمل"</string>
+    <string name="category_private" msgid="4244892185452788977">"ملف شخصي"</string>
     <string name="category_clone" msgid="1554511758987195974">"استنساخ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"خيارات المطورين"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"تفعيل خيارات المطورين"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 8eff4f6..86b29c6 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"প্ৰ’ফাইল বাছনি কৰক"</string>
     <string name="category_personal" msgid="6236798763159385225">"ব্যক্তিগত"</string>
     <string name="category_work" msgid="4014193632325996115">"কৰ্মস্থান-সম্পৰ্কীয়"</string>
+    <string name="category_private" msgid="4244892185452788977">"ব্যক্তিগত"</string>
     <string name="category_clone" msgid="1554511758987195974">"ক্ল’ন"</string>
     <string name="development_settings_title" msgid="140296922921597393">"বিকাশকৰ্তাৰ বিকল্পসমূহ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"বিকাশকৰ্তা বিষয়ক বিকল্পসমূহ সক্ষম কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index dfd1b7b..6a08a25 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil seçin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Şəxsi"</string>
     <string name="category_work" msgid="4014193632325996115">"İş"</string>
+    <string name="category_private" msgid="4244892185452788977">"Şəxsi"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonlayın"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer seçimləri"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Developer variantlarını aktiv edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 528e96e..ad829b9 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Izaberite profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Lično"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privatno"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonirano"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za programere"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 52614b7..7cd748c 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Выбраць профіль"</string>
     <string name="category_personal" msgid="6236798763159385225">"Асабісты"</string>
     <string name="category_work" msgid="4014193632325996115">"Працоўны"</string>
+    <string name="category_private" msgid="4244892185452788977">"Прыватныя"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Параметры распрацоўшчыка"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Уключыць параметры распрацоўшчыка"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index b28ae67..93fe481 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Избор на потребителски профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лични"</string>
     <string name="category_work" msgid="4014193632325996115">"Служебни"</string>
+    <string name="category_private" msgid="4244892185452788977">"Частен"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клониране"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Опции за програмисти"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Активиране на опциите за програмисти"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index c91f14c..efdf304 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"প্রোফাইল বেছে নিন"</string>
     <string name="category_personal" msgid="6236798763159385225">"ব্যক্তিগত"</string>
     <string name="category_work" msgid="4014193632325996115">"অফিস"</string>
+    <string name="category_private" msgid="4244892185452788977">"ব্যক্তিগত"</string>
     <string name="category_clone" msgid="1554511758987195974">"ক্লোন"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ডেভেলপার বিকল্প"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ডেভেলপার বিকল্প সক্ষম করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index aa1073d..5d21dea 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Odaberite profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Lično"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privatno"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonirajte"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za programere"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index ab6393a7..ea4a2fb 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Tria un perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Treball"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clona"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcions per a desenvolupadors"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activa les opcions per a desenvolupadors"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index e7d5243..648e8dd 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Vyberte profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobní"</string>
     <string name="category_work" msgid="4014193632325996115">"Pracovní"</string>
+    <string name="category_private" msgid="4244892185452788977">"Soukromé"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pro vývojáře"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivovat možnosti pro vývojáře"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 1612ac0..500bfc3 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Vælg profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personlig"</string>
     <string name="category_work" msgid="4014193632325996115">"Arbejde"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Indstillinger for udviklere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivér indstillinger for udviklere"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 73a44f1..df392f3 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -216,6 +216,8 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil auswählen"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privat"</string>
     <string name="category_work" msgid="4014193632325996115">"Geschäftlich"</string>
+    <!-- no translation found for category_private (4244892185452788977) -->
+    <skip />
     <string name="category_clone" msgid="1554511758987195974">"Klonen"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Entwickleroptionen"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Entwickleroptionen aktivieren"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 7dfd679..a87c0d7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Επιλογή προφίλ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Προσωπικό"</string>
     <string name="category_work" msgid="4014193632325996115">"Εργασίας"</string>
+    <string name="category_private" msgid="4244892185452788977">"Ιδιωτικό"</string>
     <string name="category_clone" msgid="1554511758987195974">"Κλωνοποίηση"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Επιλογές για προγραμματιστές"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ενεργοποίηση επιλογών για προγραμματιστές"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index aead40d..5193f9b 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_private" msgid="4244892185452788977">"Private"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 46dd47d..11a39b2 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_private" msgid="4244892185452788977">"Private"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index aead40d..5193f9b 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_private" msgid="4244892185452788977">"Private"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index aead40d..5193f9b 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Choose profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Work"</string>
+    <string name="category_private" msgid="4244892185452788977">"Private"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Developer options"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Enable developer options"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index a7c327f76..8a32195 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎Choose profile‎‏‎‎‏‎"</string>
     <string name="category_personal" msgid="6236798763159385225">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎Personal‎‏‎‎‏‎"</string>
     <string name="category_work" msgid="4014193632325996115">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎Work‎‏‎‎‏‎"</string>
+    <string name="category_private" msgid="4244892185452788977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎Private‎‏‎‎‏‎"</string>
     <string name="category_clone" msgid="1554511758987195974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎Clone‎‏‎‎‏‎"</string>
     <string name="development_settings_title" msgid="140296922921597393">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‎Developer options‎‏‎‎‏‎"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎Enable developer options‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 291a68b..4276f59 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Elegir perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabajo"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privado"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opciones para desarrolladores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activar opciones para programador"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b4bc319..8b7b211 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Seleccionar perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabajo"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privado"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opciones para desarrolladores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Habilitar opciones para desarrolladores"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index e5cbaf6..9c46b6c 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profiili valimine"</string>
     <string name="category_personal" msgid="6236798763159385225">"Isiklik"</string>
     <string name="category_work" msgid="4014193632325996115">"Töö"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privaatne"</string>
     <string name="category_clone" msgid="1554511758987195974">"Kloonimine"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Arendaja valikud"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Arendaja valikute lubamine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 90d45eb..4436d52 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Aukeratu profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pertsonalak"</string>
     <string name="category_work" msgid="4014193632325996115">"Lanekoak"</string>
+    <string name="category_private" msgid="4244892185452788977">"Pribatua"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonatu"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Garatzaileentzako aukerak"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Gaitu garatzaileen aukerak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f3f97c4..7ae6b7b 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"انتخاب نمایه"</string>
     <string name="category_personal" msgid="6236798763159385225">"شخصی"</string>
     <string name="category_work" msgid="4014193632325996115">"کاری"</string>
+    <string name="category_private" msgid="4244892185452788977">"خصوصی"</string>
     <string name="category_clone" msgid="1554511758987195974">"مشابه‌سازی"</string>
     <string name="development_settings_title" msgid="140296922921597393">"گزینه‌های برنامه‌نویسان"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"فعال کردن گزینه‌های برنامه‌نویس"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 7f3d0f2..6822d08 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Valitse profiili"</string>
     <string name="category_personal" msgid="6236798763159385225">"Henkilökohtainen"</string>
     <string name="category_work" msgid="4014193632325996115">"Työ"</string>
+    <string name="category_private" msgid="4244892185452788977">"Yksityinen"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klooni"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Kehittäjäasetukset"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ota kehittäjäasetukset käyttöön"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b7c3a81..12bc78e 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Sélectionnez un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personnel"</string>
     <string name="category_work" msgid="4014193632325996115">"Professionnel"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privés"</string>
     <string name="category_clone" msgid="1554511758987195974">"Cloner"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index a9e0c6a..527b473 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Sélectionner un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Perso"</string>
     <string name="category_work" msgid="4014193632325996115">"Pro"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privé"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Options pour les développeurs"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les développeurs"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 09c2969..00d7b6e 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escoller perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Traballo"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privado"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clonar"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcións para programadores"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activar opcións para programadores"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 575c675..b0819fb 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"પ્રોફાઇલ પસંદ કરો"</string>
     <string name="category_personal" msgid="6236798763159385225">"વ્યક્તિગત"</string>
     <string name="category_work" msgid="4014193632325996115">"ઑફિસ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ખાનગી"</string>
     <string name="category_clone" msgid="1554511758987195974">"ક્લોન કરો"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ડેવલપરના વિકલ્પો"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"વિકાસકર્તાનાં વિકલ્પો સક્ષમ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 655fac0..99572f3 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"प्रोफ़ाइल चुनें"</string>
     <string name="category_personal" msgid="6236798763159385225">"निजी"</string>
     <string name="category_work" msgid="4014193632325996115">"वर्क"</string>
+    <string name="category_private" msgid="4244892185452788977">"निजी"</string>
     <string name="category_clone" msgid="1554511758987195974">"क्लोन"</string>
     <string name="development_settings_title" msgid="140296922921597393">"डेवलपर के लिए सेटिंग और टूल"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"डेवलपर के लिए सेटिंग और टूल चालू करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f0e16a4..735d3e9 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Odabir profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobno"</string>
     <string name="category_work" msgid="4014193632325996115">"Posao"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privatno"</string>
     <string name="category_clone" msgid="1554511758987195974">"Kloniranje"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcije za razvojne programere"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogući opcije za razvojne programere"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 420e0e9..70b7d581 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil kiválasztása"</string>
     <string name="category_personal" msgid="6236798763159385225">"Személyes"</string>
     <string name="category_work" msgid="4014193632325996115">"Munkahelyi"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privát"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klónozás"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Fejlesztői beállítások"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Fejlesztői beállítások engedélyezése"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 705fcf6..9340a3b 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Ընտրեք պրոֆիլ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Անձնական"</string>
     <string name="category_work" msgid="4014193632325996115">"Աշխատանքային"</string>
+    <string name="category_private" msgid="4244892185452788977">"Անձնական"</string>
     <string name="category_clone" msgid="1554511758987195974">"Կլոն"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Մշակողի ընտրանքներ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Միացնել մշակողի ընտրանքները"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e33dd05..8cb3dca 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pribadi"</string>
     <string name="category_work" msgid="4014193632325996115">"Kerja"</string>
+    <string name="category_private" msgid="4244892185452788977">"Pribadi"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opsi developer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktifkan opsi developer"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index e1fb248..2f8ee7e 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Veldu snið"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persónulegt"</string>
     <string name="category_work" msgid="4014193632325996115">"Vinna"</string>
+    <string name="category_private" msgid="4244892185452788977">"Lokað"</string>
     <string name="category_clone" msgid="1554511758987195974">"Afrit"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Forritunarkostir"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Virkja valkosti þróunaraðila"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b2cfd37..9fe9f30 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Scegli profilo"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personale"</string>
     <string name="category_work" msgid="4014193632325996115">"Lavoro"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privato"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opzioni sviluppatore"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Attiva Opzioni sviluppatore"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 9ca7477..56ce9649 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"בחירת פרופיל"</string>
     <string name="category_personal" msgid="6236798763159385225">"אישי"</string>
     <string name="category_work" msgid="4014193632325996115">"עבודה"</string>
+    <string name="category_private" msgid="4244892185452788977">"פרטי"</string>
     <string name="category_clone" msgid="1554511758987195974">"שכפול"</string>
     <string name="development_settings_title" msgid="140296922921597393">"אפשרויות למפתחים"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"הפעלת אפשרויות למפתחים"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index dcce2b4..50f57ef 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"プロファイルの選択"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人用"</string>
     <string name="category_work" msgid="4014193632325996115">"仕事用"</string>
+    <string name="category_private" msgid="4244892185452788977">"非公開"</string>
     <string name="category_clone" msgid="1554511758987195974">"クローン"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開発者向けオプション"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"開発者向けオプションの有効化"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index eb32e1c..46e406d 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"აირჩიეთ პროფილი"</string>
     <string name="category_personal" msgid="6236798763159385225">"პირადი"</string>
     <string name="category_work" msgid="4014193632325996115">"სამსახური"</string>
+    <string name="category_private" msgid="4244892185452788977">"პირადი"</string>
     <string name="category_clone" msgid="1554511758987195974">"კლონის შექმნა"</string>
     <string name="development_settings_title" msgid="140296922921597393">"პარამეტრები დეველოპერებისთვის"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"დეველოპერთა პარამეტრების ჩართვა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 73a8efd..42c8ca7 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профильді таңдау"</string>
     <string name="category_personal" msgid="6236798763159385225">"Жеке"</string>
     <string name="category_work" msgid="4014193632325996115">"Жұмыс"</string>
+    <string name="category_private" msgid="4244892185452788977">"Жеке"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клондау"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Әзірлеуші опциялары"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Әзірлеуші ​​параметрлерін қосу"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 1c32e62..9503049 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ជ្រើសរើស​កម្រងព័ត៌មាន"</string>
     <string name="category_personal" msgid="6236798763159385225">"ផ្ទាល់ខ្លួន"</string>
     <string name="category_work" msgid="4014193632325996115">"ការងារ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ឯកជន"</string>
     <string name="category_clone" msgid="1554511758987195974">"ក្លូន"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ជម្រើសសម្រាប់អ្នកអភិវឌ្ឍន៍"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"បើកដំណើរការជម្រើសអ្នកអភិវឌ្ឍន៍"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ede347d..f9ec91f 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ಪ್ರೊಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ವೈಯಕ್ತಿಕ"</string>
     <string name="category_work" msgid="4014193632325996115">"ಕೆಲಸ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ಖಾಸಗಿ"</string>
     <string name="category_clone" msgid="1554511758987195974">"ಕ್ಲೋನ್"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 78bd616..a180880 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"프로필 선택"</string>
     <string name="category_personal" msgid="6236798763159385225">"개인"</string>
     <string name="category_work" msgid="4014193632325996115">"직장"</string>
+    <string name="category_private" msgid="4244892185452788977">"비공개"</string>
     <string name="category_clone" msgid="1554511758987195974">"복사"</string>
     <string name="development_settings_title" msgid="140296922921597393">"개발자 옵션"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"개발자 옵션 사용"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index a0b9123..b47356b 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профиль тандоо"</string>
     <string name="category_personal" msgid="6236798763159385225">"Жеке"</string>
     <string name="category_work" msgid="4014193632325996115">"Жумуш"</string>
+    <string name="category_private" msgid="4244892185452788977">"Купуя"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Иштеп чыгуучунун параметрлери"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Иштеп чыгуучунун параметрлерин иштетүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 96b2dc1..228eebe 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ເລືອກໂປຣໄຟລ໌"</string>
     <string name="category_personal" msgid="6236798763159385225">"​ສ່ວນ​ໂຕ"</string>
     <string name="category_work" msgid="4014193632325996115">"​ບ່ອນ​ເຮັດ​ວຽກ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ສ່ວນຕົວ"</string>
     <string name="category_clone" msgid="1554511758987195974">"ໂຄລນ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ຕົວເລືອກນັກພັດທະນາ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ເປີດໃຊ້ຕົວເລືອກນັກພັດທະນາ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 69630f4..5dfd2f4 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profilio pasirinkimas"</string>
     <string name="category_personal" msgid="6236798763159385225">"Asmeninės"</string>
     <string name="category_work" msgid="4014193632325996115">"Darbo"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privatus"</string>
     <string name="category_clone" msgid="1554511758987195974">"Identiška kopija"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Kūrėjo parinktys"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Įgalinti kūrėjo parinktis"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 4f76cee..8b55355 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profila izvēlēšanās"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privāts"</string>
     <string name="category_work" msgid="4014193632325996115">"Darba"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privāti"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klons"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Izstrādātāju opcijas"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Izstrādātāju opciju iespējošana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 1c80c65..72fea47 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Изберете профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лични"</string>
     <string name="category_work" msgid="4014193632325996115">"Работа"</string>
+    <string name="category_private" msgid="4244892185452788977">"Приватен"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Програмерски опции"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Овозможете ги програмерските опции"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 31e3c83..6308083f 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"പ്രൊഫൈൽ തിരഞ്ഞെടുക്കുക"</string>
     <string name="category_personal" msgid="6236798763159385225">"വ്യക്തിപരം"</string>
     <string name="category_work" msgid="4014193632325996115">"ഔദ്യോഗികം"</string>
+    <string name="category_private" msgid="4244892185452788977">"സ്വകാര്യം"</string>
     <string name="category_clone" msgid="1554511758987195974">"ക്ലോൺ ചെയ്യുക"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ഡെവലപ്പർ ഓ‌പ്ഷനുകൾ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ഡെവലപ്പർ ഓ‌പ്ഷനുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 5a636d9..8707f40 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Профайл сонгох"</string>
     <string name="category_personal" msgid="6236798763159385225">"Хувийн"</string>
     <string name="category_work" msgid="4014193632325996115">"Ажил"</string>
+    <string name="category_private" msgid="4244892185452788977">"Хувийн"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Хөгжүүлэгчийн тохиргоо"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Хөгжүүлэгчийн сонголтыг идэвхжүүлэх"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 4d78e57..ab8b88c 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"प्रोफाइल निवडा"</string>
     <string name="category_personal" msgid="6236798763159385225">"वैयक्तिक"</string>
     <string name="category_work" msgid="4014193632325996115">"कार्य"</string>
+    <string name="category_private" msgid="4244892185452788977">"खाजगी"</string>
     <string name="category_clone" msgid="1554511758987195974">"क्लोन करा"</string>
     <string name="development_settings_title" msgid="140296922921597393">"डेव्हलपर पर्याय"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"डेव्हलपर पर्याय सुरू करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 2ae69bd..2841c74 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Peribadi"</string>
     <string name="category_work" msgid="4014193632325996115">"Tempat Kerja"</string>
+    <string name="category_private" msgid="4244892185452788977">"Peribadi"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pilihan pembangun"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Dayakan pilihan pembangun"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 7d6f2a7..d915370 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ပရိုဖိုင်ကို ရွေးရန်"</string>
     <string name="category_personal" msgid="6236798763159385225">"ကိုယ်ပိုင်"</string>
     <string name="category_work" msgid="4014193632325996115">"အလုပ်"</string>
+    <string name="category_private" msgid="4244892185452788977">"သီးသန့်"</string>
     <string name="category_clone" msgid="1554511758987195974">"ပုံတူပွားရန်"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ဆော့ဝဲလ်ရေးသူ ရွေးစရာများ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ဆော့ဖ်ဝဲရေးသူအတွက် ရွေးစရာများကို ဖွင့်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 9e550fb..0a63c4b 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Velg profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personlig"</string>
     <string name="category_work" msgid="4014193632325996115">"Jobb"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Utvikleralternativer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Slå på utvikleralternativer"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 1f6ad5b..206444d 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"प्रोफाइल रोज्नुहोस्"</string>
     <string name="category_personal" msgid="6236798763159385225">"व्यक्तिगत"</string>
     <string name="category_work" msgid="4014193632325996115">"काम"</string>
+    <string name="category_private" msgid="4244892185452788977">"निजी"</string>
     <string name="category_clone" msgid="1554511758987195974">"क्लोन"</string>
     <string name="development_settings_title" msgid="140296922921597393">"विकासकर्ताका विकल्पहरू"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"विकासकर्ता विकल्प सक्रिया गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 6a6f184..af4797c9 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profiel kiezen"</string>
     <string name="category_personal" msgid="6236798763159385225">"Persoonlijk"</string>
     <string name="category_work" msgid="4014193632325996115">"Werk"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privé"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonen"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Ontwikkelaarsopties"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Opties voor ontwikkelaars aanzetten"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 980a374..bbdafc8 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ପ୍ରୋଫାଇଲ୍‌ ବାଛନ୍ତୁ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ବ୍ୟକ୍ତିଗତ"</string>
     <string name="category_work" msgid="4014193632325996115">"ୱାର୍କ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ପ୍ରାଇଭେଟ"</string>
     <string name="category_clone" msgid="1554511758987195974">"କ୍ଲୋନ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ଡେଭଲପରଙ୍କ ପାଇଁ ବିକଳ୍ପଗୁଡ଼ିକ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ଡେଭଲପର୍‌ ବିକଳ୍ପଗୁଡ଼ିକ ସକ୍ଷମ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index dd3fa15..59eec15 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ਪ੍ਰੋਫਾਈਲ ਚੁਣੋ"</string>
     <string name="category_personal" msgid="6236798763159385225">"ਨਿੱਜੀ"</string>
     <string name="category_work" msgid="4014193632325996115">"ਕੰਮ ਸੰਬੰਧੀ"</string>
+    <string name="category_private" msgid="4244892185452788977">"ਨਿੱਜੀ"</string>
     <string name="category_clone" msgid="1554511758987195974">"ਕਲੋਨ ਕਰੋ"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index f4ebd29..d5d37f0 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Wybierz profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobiste"</string>
     <string name="category_work" msgid="4014193632325996115">"Służbowe"</string>
+    <string name="category_private" msgid="4244892185452788977">"Prywatne"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcje programisty"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje programisty"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index bb6c7d8..3b0010f28 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_private" msgid="4244892185452788977">"Particular"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções do desenvolvedor"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar opções do desenvolvedor"</string>
@@ -231,7 +232,7 @@
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para acessar e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 6bd5c2a..c817f88 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privado"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções de programador"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar as opções de programador"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index bb6c7d8..3b0010f28 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Escolher perfil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pessoal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabalho"</string>
+    <string name="category_private" msgid="4244892185452788977">"Particular"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opções do desenvolvedor"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ativar opções do desenvolvedor"</string>
@@ -231,7 +232,7 @@
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para acessar e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index f4399dc..5d855a5 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Alege un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Serviciu"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Clonează"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opțiuni pentru dezvoltatori"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activează opțiunile pentru dezvoltatori"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 5d45e29..9dac1d3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Выбор профиля"</string>
     <string name="category_personal" msgid="6236798763159385225">"Личный профиль"</string>
     <string name="category_work" msgid="4014193632325996115">"Рабочий профиль"</string>
+    <string name="category_private" msgid="4244892185452788977">"Личный профиль"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клон"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Для разработчиков"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Включить параметры для разработчиков"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 996507d..4b36694 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"පැතිකඩ තෝරන්න"</string>
     <string name="category_personal" msgid="6236798763159385225">"පෞද්ගලික"</string>
     <string name="category_work" msgid="4014193632325996115">"කාර්යාලය"</string>
+    <string name="category_private" msgid="4244892185452788977">"පෞද්ගලික"</string>
     <string name="category_clone" msgid="1554511758987195974">"ක්ලෝන කරන්න"</string>
     <string name="development_settings_title" msgid="140296922921597393">"වර්ධක විකල්ප"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"සංවර්ධක විකල්ප සබල කිරීම"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index a51acd4..30cc9fd 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Výber profilu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobné"</string>
     <string name="category_work" msgid="4014193632325996115">"Pracovné"</string>
+    <string name="category_private" msgid="4244892185452788977">"Súkromné"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klonovanie"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pre vývojárov"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Povolenie možností vývojára"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 0d7188d..127c00d 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Izbira profila"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osebno"</string>
     <string name="category_work" msgid="4014193632325996115">"Delo"</string>
+    <string name="category_private" msgid="4244892185452788977">"Zasebno"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Možnosti za razvijalce"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Omogočanje možnosti za razvijalce"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index c2bcce7..302e915 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Zgjidh profilin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personale"</string>
     <string name="category_work" msgid="4014193632325996115">"Punë"</string>
+    <string name="category_private" msgid="4244892185452788977">"Private"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klono"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opsionet e zhvilluesit"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivizo opsionet e zhvilluesit"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 09ff994..4d4ae0b 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Изаберите профил"</string>
     <string name="category_personal" msgid="6236798763159385225">"Лично"</string>
     <string name="category_work" msgid="4014193632325996115">"Посао"</string>
+    <string name="category_private" msgid="4244892185452788977">"Приватно"</string>
     <string name="category_clone" msgid="1554511758987195974">"Клонирано"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Опције за програмере"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Омогући опције за програмере"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index fdd9d8c..8fc6af6 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Välj profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Privat"</string>
     <string name="category_work" msgid="4014193632325996115">"Jobb"</string>
+    <string name="category_private" msgid="4244892185452788977">"Privat"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Utvecklaralternativ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivera utvecklaralternativ"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index bd41752..f6cb654 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Chagua wasifu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Binafsi"</string>
     <string name="category_work" msgid="4014193632325996115">"Kazini"</string>
+    <string name="category_private" msgid="4244892185452788977">"Faragha"</string>
     <string name="category_clone" msgid="1554511758987195974">"Kloni"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Chaguo za wasanidi"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Washa chaguo za wasanidi programu"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index fd379f0..41788bf 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"சுயவிவரத்தைத் தேர்வு செய்க"</string>
     <string name="category_personal" msgid="6236798763159385225">"தனிப்பட்டவை"</string>
     <string name="category_work" msgid="4014193632325996115">"பணியிடம்"</string>
+    <string name="category_private" msgid="4244892185452788977">"தனிப்பட்டவை"</string>
     <string name="category_clone" msgid="1554511758987195974">"குளோன்"</string>
     <string name="development_settings_title" msgid="140296922921597393">"டெவெலப்பர் விருப்பங்கள்"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"டெவெலப்பர் விருப்பங்களை இயக்கு"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 3e9d8be..4c71251 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"ప్రొఫైల్‌ను ఎంచుకోండి"</string>
     <string name="category_personal" msgid="6236798763159385225">"వ్యక్తిగతం"</string>
     <string name="category_work" msgid="4014193632325996115">"వర్క్"</string>
+    <string name="category_private" msgid="4244892185452788977">"ప్రైవేట్"</string>
     <string name="category_clone" msgid="1554511758987195974">"క్లోన్ చేయండి"</string>
     <string name="development_settings_title" msgid="140296922921597393">"డెవలపర్ ఆప్షన్‌లు"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"డెవలపర్ ఎంపికలను ప్రారంభించండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index e67f371..cb6291a 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"เลือกโปรไฟล์"</string>
     <string name="category_personal" msgid="6236798763159385225">"ส่วนตัว"</string>
     <string name="category_work" msgid="4014193632325996115">"งาน"</string>
+    <string name="category_private" msgid="4244892185452788977">"ส่วนตัว"</string>
     <string name="category_clone" msgid="1554511758987195974">"โคลน"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ตัวเลือกสำหรับนักพัฒนาแอป"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอป"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 440bbe7..44d5de2 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Pumili ng profile"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personal"</string>
     <string name="category_work" msgid="4014193632325996115">"Trabaho"</string>
+    <string name="category_private" msgid="4244892185452788977">"Pribado"</string>
     <string name="category_clone" msgid="1554511758987195974">"I-clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Mga opsyon ng developer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"I-enable ang mga opsyon ng developer"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index b38012f..e33afa1 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -141,7 +141,7 @@
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"İptal"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Eşleme işlemi, bağlantı kurulduğunda kişilerinize ve çağrı geçmişine erişim izni verir."</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşlenemedi."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN veya şifre anahtarı yanlış olduğundan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşlenemedi."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN veya geçiş anahtarı yanlış olduğundan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşlenemedi."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile iletişim kurulamıyor."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Eşleme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tarafından reddedildi."</string>
     <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Bilgisayar"</string>
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profil seçin"</string>
     <string name="category_personal" msgid="6236798763159385225">"Kişisel"</string>
     <string name="category_work" msgid="4014193632325996115">"İş"</string>
+    <string name="category_private" msgid="4244892185452788977">"Gizli"</string>
     <string name="category_clone" msgid="1554511758987195974">"Klon"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Geliştirici seçenekleri"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Geliştirici seçeneklerini etkinleştir"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 4f08547..319caca 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Вибрати профіль"</string>
     <string name="category_personal" msgid="6236798763159385225">"Особисте"</string>
     <string name="category_work" msgid="4014193632325996115">"Робоче"</string>
+    <string name="category_private" msgid="4244892185452788977">"Приватні"</string>
     <string name="category_clone" msgid="1554511758987195974">"Копія профілю"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Параметри розробника"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Увімкнути параметри розробника"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index ce67d15..10dacde 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"پروفائل منتخب کریں"</string>
     <string name="category_personal" msgid="6236798763159385225">"ذاتی"</string>
     <string name="category_work" msgid="4014193632325996115">"دفتر"</string>
+    <string name="category_private" msgid="4244892185452788977">"نجی"</string>
     <string name="category_clone" msgid="1554511758987195974">"کلون کریں"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ڈویلپر کے اختیارات"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ڈویلپر کے اختیارات فعال کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 77da981..0a85c28 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Profilni tanlang"</string>
     <string name="category_personal" msgid="6236798763159385225">"Shaxsiy"</string>
     <string name="category_work" msgid="4014193632325996115">"Ish"</string>
+    <string name="category_private" msgid="4244892185452788977">"Yopiq"</string>
     <string name="category_clone" msgid="1554511758987195974">"Nusxalash"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Dasturchi sozlamalari"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Dasturchi sozlamalarini yoqish"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index bf510f6..3c34f4d 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Chọn hồ sơ"</string>
     <string name="category_personal" msgid="6236798763159385225">"Cá nhân"</string>
     <string name="category_work" msgid="4014193632325996115">"Công việc"</string>
+    <string name="category_private" msgid="4244892185452788977">"Riêng tư"</string>
     <string name="category_clone" msgid="1554511758987195974">"Nhân bản"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Tùy chọn cho nhà phát triển"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Bật tùy chọn nhà phát triển"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 8e3145a..d385e67 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"选择个人资料"</string>
     <string name="category_personal" msgid="6236798763159385225">"个人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_private" msgid="4244892185452788977">"私享"</string>
     <string name="category_clone" msgid="1554511758987195974">"克隆"</string>
     <string name="development_settings_title" msgid="140296922921597393">"开发者选项"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"启用开发者选项"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index aa9f21f..adcb4d8 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"選擇設定檔"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_private" msgid="4244892185452788977">"私人"</string>
     <string name="category_clone" msgid="1554511758987195974">"複製"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開發人員選項"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"啟用開發人員選項"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 3c65a4d..fddef2b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"選擇設定檔"</string>
     <string name="category_personal" msgid="6236798763159385225">"個人"</string>
     <string name="category_work" msgid="4014193632325996115">"工作"</string>
+    <string name="category_private" msgid="4244892185452788977">"私人"</string>
     <string name="category_clone" msgid="1554511758987195974">"複製"</string>
     <string name="development_settings_title" msgid="140296922921597393">"開發人員選項"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"啟用開發人員選項"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 08b04cc..82b7306 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -216,6 +216,7 @@
     <string name="choose_profile" msgid="343803890897657450">"Khetha iphrofayela"</string>
     <string name="category_personal" msgid="6236798763159385225">"Okomuntu siqu"</string>
     <string name="category_work" msgid="4014193632325996115">"Umsebenzi"</string>
+    <string name="category_private" msgid="4244892185452788977">"Okuyimfihlo"</string>
     <string name="category_clone" msgid="1554511758987195974">"Yenza i-clone"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Izinketho Zonjiniyela"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Nika amandla izinketho zonjiniyela"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
index 57867be..f83e37b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
@@ -19,6 +19,9 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
+import android.annotation.CallbackExecutor;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
@@ -28,10 +31,11 @@
 import android.os.Build;
 import android.util.Log;
 
+import androidx.annotation.RequiresApi;
+
 import java.util.ArrayList;
 import java.util.List;
-
-import androidx.annotation.RequiresApi;
+import java.util.concurrent.Executor;
 
 /**
  * VolumeControlProfile handles Bluetooth Volume Control Controller role
@@ -102,6 +106,88 @@
                 BluetoothProfile.VOLUME_CONTROL);
     }
 
+
+    /**
+     * Registers a {@link BluetoothVolumeControl.Callback} that will be invoked during the
+     * operation of this profile.
+     *
+     * Repeated registration of the same <var>callback</var> object will have no effect after
+     * the first call to this method, even when the <var>executor</var> is different. API caller
+     * would have to call {@link #unregisterCallback(BluetoothVolumeControl.Callback)} with
+     * the same callback object before registering it again.
+     *
+     * @param executor an {@link Executor} to execute given callback
+     * @param callback user implementation of the {@link BluetoothVolumeControl.Callback}
+     * @throws IllegalArgumentException if a null executor or callback is given
+     */
+    public void registerCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull BluetoothVolumeControl.Callback callback) {
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service. Cannot register callback.");
+            return;
+        }
+        mService.registerCallback(executor, callback);
+    }
+
+    /**
+     * Unregisters the specified {@link BluetoothVolumeControl.Callback}.
+     * <p>The same {@link BluetoothVolumeControl.Callback} object used when calling
+     * {@link #registerCallback(Executor, BluetoothVolumeControl.Callback)} must be used.
+     *
+     * <p>Callbacks are automatically unregistered when application process goes away
+     *
+     * @param callback user implementation of the {@link BluetoothVolumeControl.Callback}
+     * @throws IllegalArgumentException when callback is null or when no callback is registered
+     */
+    public void unregisterCallback(@NonNull BluetoothVolumeControl.Callback callback) {
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service. Cannot unregister callback.");
+            return;
+        }
+        mService.unregisterCallback(callback);
+    }
+
+    /**
+     * Tells the remote device to set a volume offset to the absolute volume.
+     *
+     * @param device {@link BluetoothDevice} representing the remote device
+     * @param volumeOffset volume offset to be set on the remote device
+     */
+    public void setVolumeOffset(BluetoothDevice device,
+            @IntRange(from = -255, to = 255) int volumeOffset) {
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service. Cannot set volume offset.");
+            return;
+        }
+        if (device == null) {
+            Log.w(TAG, "Device is null. Cannot set volume offset.");
+            return;
+        }
+        mService.setVolumeOffset(device, volumeOffset);
+    }
+
+    /**
+     * Provides information about the possibility to set volume offset on the remote device.
+     * If the remote device supports Volume Offset Control Service, it is automatically
+     * connected.
+     *
+     * @param device {@link BluetoothDevice} representing the remote device
+     * @return {@code true} if volume offset function is supported and available to use on the
+     *         remote device. When Bluetooth is off, the return value should always be
+     *         {@code false}.
+     */
+    public boolean isVolumeOffsetAvailable(BluetoothDevice device) {
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service. Cannot get is volume offset available.");
+            return false;
+        }
+        if (device == null) {
+            Log.w(TAG, "Device is null. Cannot get is volume offset available.");
+            return false;
+        }
+        return mService.isVolumeOffsetAvailable(device);
+    }
+
     @Override
     public boolean accessProfileEnabled() {
         return false;
@@ -113,12 +199,12 @@
     }
 
     /**
-     * Get VolumeControlProfile devices matching connection states{
+     * Gets VolumeControlProfile devices matching connection states{
+     * {@code BluetoothProfile.STATE_CONNECTED},
+     * {@code BluetoothProfile.STATE_CONNECTING},
+     * {@code BluetoothProfile.STATE_DISCONNECTING}}
      *
      * @return Matching device list
-     * @code BluetoothProfile.STATE_CONNECTED,
-     * @code BluetoothProfile.STATE_CONNECTING,
-     * @code BluetoothProfile.STATE_DISCONNECTING}
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (mService == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SettingsJankMonitor.kt b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SettingsJankMonitor.kt
index a5f69ff..02d76304 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SettingsJankMonitor.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SettingsJankMonitor.kt
@@ -18,7 +18,7 @@
 import android.view.View
 import androidx.annotation.VisibleForTesting
 import androidx.preference.PreferenceGroupAdapter
-import androidx.preference.SwitchPreference
+import androidx.preference.TwoStatePreference
 import androidx.recyclerview.widget.RecyclerView
 import com.android.internal.jank.InteractionJankMonitor
 import java.util.concurrent.Executors
@@ -43,7 +43,10 @@
      * @param preference the clicked preference
      */
     @JvmStatic
-    fun detectSwitchPreferenceClickJank(recyclerView: RecyclerView, preference: SwitchPreference) {
+    fun detectSwitchPreferenceClickJank(
+        recyclerView: RecyclerView,
+        preference: TwoStatePreference,
+    ) {
         val adapter = recyclerView.adapter as? PreferenceGroupAdapter ?: return
         val adapterPosition = adapter.getPreferenceAdapterPosition(preference)
         val viewHolder = recyclerView.findViewHolderForAdapterPosition(adapterPosition) ?: return
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
index 70956e9..9ab3b47 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/RouterInfoMediaManager.java
@@ -38,6 +38,7 @@
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /** Implements {@link InfoMediaManager} using {@link MediaRouter2}. */
@@ -54,8 +55,11 @@
     private final RouteCallback mRouteCallback = new RouteCallback();
     private final TransferCallback mTransferCallback = new TransferCallback();
     private final ControllerCallback mControllerCallback = new ControllerCallback();
-    private final RouteListingPreferenceCallback mRouteListingPreferenceCallback =
-            new RouteListingPreferenceCallback();
+    private final Consumer<RouteListingPreference> mRouteListingPreferenceCallback =
+            (preference) -> {
+                notifyRouteListingPreferenceUpdated(preference);
+                refreshDevices();
+            };
 
     // TODO: b/192657812 - Create factory method in InfoMediaManager to return
     //      RouterInfoMediaManager or ManagerInfoMediaManager based on flag.
@@ -83,7 +87,8 @@
     @Override
     protected void startScanOnRouter() {
         mRouter.registerRouteCallback(mExecutor, mRouteCallback, RouteDiscoveryPreference.EMPTY);
-        mRouter.registerRouteListingPreferenceCallback(mExecutor, mRouteListingPreferenceCallback);
+        mRouter.registerRouteListingPreferenceUpdatedCallback(
+                mExecutor, mRouteListingPreferenceCallback);
         mRouter.registerTransferCallback(mExecutor, mTransferCallback);
         mRouter.registerControllerCallback(mExecutor, mControllerCallback);
         mRouter.startScan();
@@ -94,7 +99,7 @@
         mRouter.stopScan();
         mRouter.unregisterControllerCallback(mControllerCallback);
         mRouter.unregisterTransferCallback(mTransferCallback);
-        mRouter.unregisterRouteListingPreferenceCallback(mRouteListingPreferenceCallback);
+        mRouter.unregisterRouteListingPreferenceUpdatedCallback(mRouteListingPreferenceCallback);
         mRouter.unregisterRouteCallback(mRouteCallback);
     }
 
@@ -308,13 +313,4 @@
             refreshDevices();
         }
     }
-
-    private final class RouteListingPreferenceCallback
-            extends MediaRouter2.RouteListingPreferenceCallback {
-        @Override
-        public void onRouteListingPreferenceChanged(@Nullable RouteListingPreference preference) {
-            notifyRouteListingPreferenceUpdated(preference);
-            refreshDevices();
-        }
-    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/VolumeControlProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/VolumeControlProfileTest.java
new file mode 100644
index 0000000..c560627
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/VolumeControlProfileTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.bluetooth;
+
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothVolumeControl;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class VolumeControlProfileTest {
+
+    private static final int TEST_VOLUME_OFFSET = 10;
+
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    @Mock
+    private BluetoothVolumeControl mService;
+
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private VolumeControlProfile mProfile;
+
+    @Before
+    public void setUp() {
+        mProfile = new VolumeControlProfile(mContext, mDeviceManager, mProfileManager);
+        final BluetoothManager bluetoothManager = mContext.getSystemService(BluetoothManager.class);
+        final ShadowBluetoothAdapter shadowBluetoothAdapter =
+                Shadow.extract(bluetoothManager.getAdapter());
+        mServiceListener = shadowBluetoothAdapter.getServiceListener();
+    }
+
+    @Test
+    public void onServiceConnected_isProfileReady() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+
+        assertThat(mProfile.isProfileReady()).isTrue();
+        verify(mProfileManager).callServiceConnectedListeners();
+    }
+
+    @Test
+    public void onServiceDisconnected_isProfileNotReady() {
+        mServiceListener.onServiceDisconnected(BluetoothProfile.VOLUME_CONTROL);
+
+        assertThat(mProfile.isProfileReady()).isFalse();
+        verify(mProfileManager).callServiceDisconnectedListeners();
+    }
+
+    @Test
+    public void getConnectionStatus_returnCorrectConnectionState() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionState(mBluetoothDevice))
+                .thenReturn(BluetoothProfile.STATE_CONNECTED);
+
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice))
+                .isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+
+    @Test
+    public void isEnabled_connectionPolicyAllowed_returnTrue() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice)).thenReturn(CONNECTION_POLICY_ALLOWED);
+
+        assertThat(mProfile.isEnabled(mBluetoothDevice)).isTrue();
+    }
+
+    @Test
+    public void isEnabled_connectionPolicyForbidden_returnFalse() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice))
+                .thenReturn(CONNECTION_POLICY_FORBIDDEN);
+
+        assertThat(mProfile.isEnabled(mBluetoothDevice)).isFalse();
+    }
+
+    @Test
+    public void getConnectionPolicy_returnCorrectConnectionPolicy() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice)).thenReturn(CONNECTION_POLICY_ALLOWED);
+
+        assertThat(mProfile.getConnectionPolicy(mBluetoothDevice))
+                .isEqualTo(CONNECTION_POLICY_ALLOWED);
+    }
+
+    @Test
+    public void setEnabled_connectionPolicyAllowed_setConnectionPolicyAllowed_returnFalse() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice)).thenReturn(CONNECTION_POLICY_ALLOWED);
+        when(mService.setConnectionPolicy(mBluetoothDevice, CONNECTION_POLICY_ALLOWED))
+                .thenReturn(true);
+
+        assertThat(mProfile.setEnabled(mBluetoothDevice, true)).isFalse();
+    }
+
+    @Test
+    public void setEnabled_connectionPolicyForbidden_setConnectionPolicyAllowed_returnTrue() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice))
+                .thenReturn(CONNECTION_POLICY_FORBIDDEN);
+        when(mService.setConnectionPolicy(mBluetoothDevice, CONNECTION_POLICY_ALLOWED))
+                .thenReturn(true);
+
+        assertThat(mProfile.setEnabled(mBluetoothDevice, true)).isTrue();
+    }
+
+    @Test
+    public void setEnabled_connectionPolicyAllowed_setConnectionPolicyForbidden_returnTrue() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice)).thenReturn(CONNECTION_POLICY_ALLOWED);
+        when(mService.setConnectionPolicy(mBluetoothDevice, CONNECTION_POLICY_FORBIDDEN))
+                .thenReturn(true);
+
+        assertThat(mProfile.setEnabled(mBluetoothDevice, false)).isTrue();
+    }
+
+    @Test
+    public void setEnabled_connectionPolicyForbidden_setConnectionPolicyForbidden_returnTrue() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.getConnectionPolicy(mBluetoothDevice))
+                .thenReturn(CONNECTION_POLICY_FORBIDDEN);
+        when(mService.setConnectionPolicy(mBluetoothDevice, CONNECTION_POLICY_FORBIDDEN))
+                .thenReturn(true);
+
+        assertThat(mProfile.setEnabled(mBluetoothDevice, false)).isTrue();
+    }
+
+    @Test
+    public void getConnectedDevices_returnCorrectList() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        int[] connectedStates = new int[] {
+                BluetoothProfile.STATE_CONNECTED,
+                BluetoothProfile.STATE_CONNECTING,
+                BluetoothProfile.STATE_DISCONNECTING};
+        List<BluetoothDevice> connectedList = Arrays.asList(
+                mBluetoothDevice,
+                mBluetoothDevice,
+                mBluetoothDevice);
+        when(mService.getDevicesMatchingConnectionStates(connectedStates))
+                .thenReturn(connectedList);
+
+        assertThat(mProfile.getConnectedDevices().size()).isEqualTo(connectedList.size());
+    }
+
+    @Test
+    public void registerCallback_verifyIsCalled() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+
+        final Executor executor = (command -> new Thread(command).start());
+        final BluetoothVolumeControl.Callback callback = (device, volumeOffset) -> {};
+        mProfile.registerCallback(executor, callback);
+
+        verify(mService).registerCallback(executor, callback);
+    }
+
+    @Test
+    public void unregisterCallback_verifyIsCalled() {
+        final BluetoothVolumeControl.Callback callback = (device, volumeOffset) -> {};
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+
+        mProfile.unregisterCallback(callback);
+
+        verify(mService).unregisterCallback(callback);
+    }
+
+    @Test
+    public void setVolumeOffset_verifyIsCalled() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+
+        mProfile.setVolumeOffset(mBluetoothDevice, TEST_VOLUME_OFFSET);
+
+        verify(mService).setVolumeOffset(mBluetoothDevice, TEST_VOLUME_OFFSET);
+    }
+
+    @Test
+    public void isVolumeOffsetAvailable_verifyIsCalledAndReturnTrue() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.isVolumeOffsetAvailable(mBluetoothDevice)).thenReturn(true);
+
+        final boolean available = mProfile.isVolumeOffsetAvailable(mBluetoothDevice);
+
+        verify(mService).isVolumeOffsetAvailable(mBluetoothDevice);
+        assertThat(available).isTrue();
+    }
+
+    @Test
+    public void isVolumeOffsetAvailable_verifyIsCalledAndReturnFalse() {
+        mServiceListener.onServiceConnected(BluetoothProfile.VOLUME_CONTROL, mService);
+        when(mService.isVolumeOffsetAvailable(mBluetoothDevice)).thenReturn(false);
+
+        final boolean available = mProfile.isVolumeOffsetAvailable(mBluetoothDevice);
+
+        verify(mService).isVolumeOffsetAvailable(mBluetoothDevice);
+        assertThat(available).isFalse();
+    }
+}
diff --git a/packages/SoundPicker/res/values-af/strings.xml b/packages/SoundPicker/res/values-af/strings.xml
index 7396b76..fd857b1 100644
--- a/packages/SoundPicker/res/values-af/strings.xml
+++ b/packages/SoundPicker/res/values-af/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kan nie gepasmaakte luitoon byvoeg nie"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kan nie gepasmaakte luitoon uitvee nie"</string>
     <string name="app_label" msgid="3091611356093417332">"Klanke"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Die lys is leeg"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Klank"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrasie"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-am/strings.xml b/packages/SoundPicker/res/values-am/strings.xml
index bd1c24b..85206c0 100644
--- a/packages/SoundPicker/res/values-am/strings.xml
+++ b/packages/SoundPicker/res/values-am/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"ብጁ የጥሪ ቅላጼን ማከል አልተቻለም"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ብጁ የጥሪ ቅላጼን መሰረዝ አልተቻለም"</string>
     <string name="app_label" msgid="3091611356093417332">"ድምፆች"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ዝርዝሩ ባዶ ነው"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ድምፅ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ንዝረት"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ar/strings.xml b/packages/SoundPicker/res/values-ar/strings.xml
index 805c7cf..f8844e9 100644
--- a/packages/SoundPicker/res/values-ar/strings.xml
+++ b/packages/SoundPicker/res/values-ar/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"يتعذر إضافة نغمة رنين مخصصة"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"يتعذر حذف نغمة الرنين المخصصة"</string>
     <string name="app_label" msgid="3091611356093417332">"الأصوات"</string>
-    <string name="empty_list" msgid="2871978423955821191">"القائمة فارغة."</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"الصوت"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"الاهتزاز"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-as/strings.xml b/packages/SoundPicker/res/values-as/strings.xml
index 0a1cd1b..5d6bc5d 100644
--- a/packages/SoundPicker/res/values-as/strings.xml
+++ b/packages/SoundPicker/res/values-as/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"নিজৰ উপযোগিতা অনুযায়ী তৈয়াৰ কৰা ৰিংট\'ন যোগ কৰিব পৰা নগ\'ল"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"নিজৰ উপযোগিতা অনুযায়ী তৈয়াৰ কৰা ৰিংট\'ন মচিব পৰা নগ\'ল"</string>
     <string name="app_label" msgid="3091611356093417332">"ধ্বনিসমূহ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"সূচীখন খালী আছে"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ধ্বনি"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"কম্পন"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-az/strings.xml b/packages/SoundPicker/res/values-az/strings.xml
index a308329..e32c3eb 100644
--- a/packages/SoundPicker/res/values-az/strings.xml
+++ b/packages/SoundPicker/res/values-az/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Fərdi zəng səsi əlavə etmək mümkün deyil"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Fərdi zəng səsini silmək mümkün deyil"</string>
     <string name="app_label" msgid="3091611356093417332">"Səslər"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Siyahı boşdur"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Səs"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrasiya"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-b+sr+Latn/strings.xml b/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
index 2a7a196..947c85c 100644
--- a/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
+++ b/packages/SoundPicker/res/values-b+sr+Latn/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Dodavanje prilagođene melodije zvona nije uspelo"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Brisanje prilagođene melodije zvona nije uspelo"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista je prazna"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvuk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibriranje"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-be/strings.xml b/packages/SoundPicker/res/values-be/strings.xml
index 431a301..6f7fc68 100644
--- a/packages/SoundPicker/res/values-be/strings.xml
+++ b/packages/SoundPicker/res/values-be/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Немагчыма дадаць карыстальніцкі рынгтон"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Немагчыма выдаліць карыстальніцкі рынгтон"</string>
     <string name="app_label" msgid="3091611356093417332">"Гукі"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Спіс пусты"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Гук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вібрацыя"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-bg/strings.xml b/packages/SoundPicker/res/values-bg/strings.xml
index 7447af6..4277d28 100644
--- a/packages/SoundPicker/res/values-bg/strings.xml
+++ b/packages/SoundPicker/res/values-bg/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Персонализираната мелодия не може да се добави"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Персонализираната мелодия не може да се изтрие"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Списъкът е празен"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Звук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вибриране"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-bn/strings.xml b/packages/SoundPicker/res/values-bn/strings.xml
index c31b36a..276594a 100644
--- a/packages/SoundPicker/res/values-bn/strings.xml
+++ b/packages/SoundPicker/res/values-bn/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"কাস্টম রিংটোন যোগ করা গেল না"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"কাস্টম রিংটোন মোছা গেল না"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"তালিকায় কিছু নেই"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"সাউন্ড"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ভাইব্রেশন"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-bs/strings.xml b/packages/SoundPicker/res/values-bs/strings.xml
index e65b90d..0c8d33f 100644
--- a/packages/SoundPicker/res/values-bs/strings.xml
+++ b/packages/SoundPicker/res/values-bs/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nije moguće dodati prilagođenu melodiju zvona"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nije moguće izbrisati prilagođenu melodiju zvona"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista je prazna"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvuk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibracija"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ca/strings.xml b/packages/SoundPicker/res/values-ca/strings.xml
index 33839bc..ed96f70 100644
--- a/packages/SoundPicker/res/values-ca/strings.xml
+++ b/packages/SoundPicker/res/values-ca/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"No es pot afegir el so de trucada personalitzat"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No es pot suprimir el so de trucada personalitzat"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"La llista és buida"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"So"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibració"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-cs/strings.xml b/packages/SoundPicker/res/values-cs/strings.xml
index 612a6b2..dc67c96 100644
--- a/packages/SoundPicker/res/values-cs/strings.xml
+++ b/packages/SoundPicker/res/values-cs/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Vlastní vyzvánění se nepodařilo přidat"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Vlastní vyzvánění se nepodařilo smazat"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvuky"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Seznam je prázdný"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvuk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrace"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-da/strings.xml b/packages/SoundPicker/res/values-da/strings.xml
index 56c4d23..b4437dc 100644
--- a/packages/SoundPicker/res/values-da/strings.xml
+++ b/packages/SoundPicker/res/values-da/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Den tilpassede ringetone kunne ikke tilføjes"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Den tilpassede ringetone kunne ikke slettes"</string>
     <string name="app_label" msgid="3091611356093417332">"Lyde"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Listen er tom"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Lyd"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-de/strings.xml b/packages/SoundPicker/res/values-de/strings.xml
index b004e2a..8be3aaa 100644
--- a/packages/SoundPicker/res/values-de/strings.xml
+++ b/packages/SoundPicker/res/values-de/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Benutzerdefinierter Klingelton konnte nicht hinzugefügt werden"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Benutzerdefinierter Klingelton konnte nicht gelöscht werden"</string>
     <string name="app_label" msgid="3091611356093417332">"Töne"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Die Liste ist leer"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ton"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-el/strings.xml b/packages/SoundPicker/res/values-el/strings.xml
index bbcb1f5..41e9b0c 100644
--- a/packages/SoundPicker/res/values-el/strings.xml
+++ b/packages/SoundPicker/res/values-el/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Δεν είναι δυνατή η προσθήκη προσαρμοσμένου ήχου κλήσης"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Δεν είναι δυνατή η διαγραφή προσαρμοσμένου ήχου κλήσης"</string>
     <string name="app_label" msgid="3091611356093417332">"Ήχοι"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Η λίστα είναι κενή"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ήχος"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Δόνηση"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-en-rAU/strings.xml b/packages/SoundPicker/res/values-en-rAU/strings.xml
index 5030314..4c237b9 100644
--- a/packages/SoundPicker/res/values-en-rAU/strings.xml
+++ b/packages/SoundPicker/res/values-en-rAU/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add customised ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete customised ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"The list is empty"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sound"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-en-rCA/strings.xml b/packages/SoundPicker/res/values-en-rCA/strings.xml
index d887082..b0708356 100644
--- a/packages/SoundPicker/res/values-en-rCA/strings.xml
+++ b/packages/SoundPicker/res/values-en-rCA/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add custom ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete custom ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"The list is empty"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sound"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-en-rGB/strings.xml b/packages/SoundPicker/res/values-en-rGB/strings.xml
index 5030314..4c237b9 100644
--- a/packages/SoundPicker/res/values-en-rGB/strings.xml
+++ b/packages/SoundPicker/res/values-en-rGB/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add customised ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete customised ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"The list is empty"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sound"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-en-rIN/strings.xml b/packages/SoundPicker/res/values-en-rIN/strings.xml
index 5030314..4c237b9 100644
--- a/packages/SoundPicker/res/values-en-rIN/strings.xml
+++ b/packages/SoundPicker/res/values-en-rIN/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add customised ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete customised ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"The list is empty"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sound"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-en-rXC/strings.xml b/packages/SoundPicker/res/values-en-rXC/strings.xml
index d26c89b..8397e0b 100644
--- a/packages/SoundPicker/res/values-en-rXC/strings.xml
+++ b/packages/SoundPicker/res/values-en-rXC/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎Unable to add custom ringtone‎‏‎‎‏‎"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‎‎‎Unable to delete custom ringtone‎‏‎‎‏‎"</string>
     <string name="app_label" msgid="3091611356093417332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎Sounds‎‏‎‎‏‎"</string>
-    <string name="empty_list" msgid="2871978423955821191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎The list is empty‎‏‎‎‏‎"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎Sound‎‏‎‎‏‎"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎Vibration‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-es-rUS/strings.xml b/packages/SoundPicker/res/values-es-rUS/strings.xml
index 211bfed..5bf73b2 100644
--- a/packages/SoundPicker/res/values-es-rUS/strings.xml
+++ b/packages/SoundPicker/res/values-es-rUS/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"No se puede agregar el tono personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No se puede borrar el tono personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sonidos"</string>
-    <string name="empty_list" msgid="2871978423955821191">"La lista está vacía"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sonido"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibración"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-es/strings.xml b/packages/SoundPicker/res/values-es/strings.xml
index 3fdad74..a77f656 100644
--- a/packages/SoundPicker/res/values-es/strings.xml
+++ b/packages/SoundPicker/res/values-es/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"No se ha podido añadir un tono de llamada personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"No se ha podido eliminar un tono de llamada personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sonidos"</string>
-    <string name="empty_list" msgid="2871978423955821191">"La lista está vacía"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sonido"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibración"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-et/strings.xml b/packages/SoundPicker/res/values-et/strings.xml
index 3d9ee94..fa680ac 100644
--- a/packages/SoundPicker/res/values-et/strings.xml
+++ b/packages/SoundPicker/res/values-et/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kohandatud helinat ei õnnestu lisada"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kohandatud helinat ei õnnestu kustutada"</string>
     <string name="app_label" msgid="3091611356093417332">"Helid"</string>
-    <string name="empty_list" msgid="2871978423955821191">"See loend on tühi"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Heli"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibreerimine"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-eu/strings.xml b/packages/SoundPicker/res/values-eu/strings.xml
index 1f929bf..e8e07fe 100644
--- a/packages/SoundPicker/res/values-eu/strings.xml
+++ b/packages/SoundPicker/res/values-eu/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Ezin da gehitu tonu pertsonalizatua"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Ezin da ezabatu tonu pertsonalizatua"</string>
     <string name="app_label" msgid="3091611356093417332">"Soinuak"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Zerrenda hutsik dago"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Soinua"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Dardara"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-fa/strings.xml b/packages/SoundPicker/res/values-fa/strings.xml
index 3b75ac9..769d5d5 100644
--- a/packages/SoundPicker/res/values-fa/strings.xml
+++ b/packages/SoundPicker/res/values-fa/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"افزودن آهنگ زنگ سفارشی ممکن نیست"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"حذف آهنگ زنگ سفارشی ممکن نیست"</string>
     <string name="app_label" msgid="3091611356093417332">"صداها"</string>
-    <string name="empty_list" msgid="2871978423955821191">"فهرست خالی است"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"صدا"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"لرزش"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-fi/strings.xml b/packages/SoundPicker/res/values-fi/strings.xml
index 15bf658..fcda098 100644
--- a/packages/SoundPicker/res/values-fi/strings.xml
+++ b/packages/SoundPicker/res/values-fi/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Muokatun soittoäänen lisääminen epäonnistui."</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Muokatun soittoäänen poistaminen epäonnistui."</string>
     <string name="app_label" msgid="3091611356093417332">"Äänet"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista on tyhjä"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ääni"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Värinä"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-fr-rCA/strings.xml b/packages/SoundPicker/res/values-fr-rCA/strings.xml
index 1cc170f..4d4545f 100644
--- a/packages/SoundPicker/res/values-fr-rCA/strings.xml
+++ b/packages/SoundPicker/res/values-fr-rCA/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Impossible d\'ajouter une sonnerie personnalisée"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Impossible de supprimer la sonnerie personnalisée"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"La liste est vide"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Son"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-fr/strings.xml b/packages/SoundPicker/res/values-fr/strings.xml
index ade2c16..9452e70 100644
--- a/packages/SoundPicker/res/values-fr/strings.xml
+++ b/packages/SoundPicker/res/values-fr/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Impossible d\'ajouter une sonnerie personnalisée"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Impossible de supprimer la sonnerie personnalisée"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"La liste est vide"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Son"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-gl/strings.xml b/packages/SoundPicker/res/values-gl/strings.xml
index 83f2b2e..59a9d06 100644
--- a/packages/SoundPicker/res/values-gl/strings.xml
+++ b/packages/SoundPicker/res/values-gl/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Non se pode engadir un ton de chamada personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Non se pode eliminar un ton de chamada personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"A lista está baleira"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Son"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibración"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-gu/strings.xml b/packages/SoundPicker/res/values-gu/strings.xml
index 8207512..209769f 100644
--- a/packages/SoundPicker/res/values-gu/strings.xml
+++ b/packages/SoundPicker/res/values-gu/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"કસ્ટમ રિંગટોન ઉમેરવામાં અસમર્થ"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"કસ્ટમ રિંગટોન કાઢી નાખવામાં અસમર્થ"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"સૂચિ ખાલી છે"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"સાઉન્ડ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"વાઇબ્રેશન"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-hi/strings.xml b/packages/SoundPicker/res/values-hi/strings.xml
index 304201f..ab3b7f8 100644
--- a/packages/SoundPicker/res/values-hi/strings.xml
+++ b/packages/SoundPicker/res/values-hi/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"आपके मुताबिक रिंगटोन नहीं जोड़ी जा सकी"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"आपके मुताबिक रिंगटोन नहीं हटाई जा सकी"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"यह सूची खाली है"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"साउंड"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"वाइब्रेशन"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-hr/strings.xml b/packages/SoundPicker/res/values-hr/strings.xml
index 642c7d5..3adc500 100644
--- a/packages/SoundPicker/res/values-hr/strings.xml
+++ b/packages/SoundPicker/res/values-hr/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Dodavanje prilagođene melodije zvona nije moguće"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Brisanje prilagođene melodije zvona nije moguće"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvukovi"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Popis je prazan"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvuk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibracija"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-hu/strings.xml b/packages/SoundPicker/res/values-hu/strings.xml
index 401da84..32d4ba9 100644
--- a/packages/SoundPicker/res/values-hu/strings.xml
+++ b/packages/SoundPicker/res/values-hu/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nem sikerült hozzáadni az egyéni csengőhangot"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nem sikerült törölni az egyéni csengőhangot"</string>
     <string name="app_label" msgid="3091611356093417332">"Hangok"</string>
-    <string name="empty_list" msgid="2871978423955821191">"A lista üres"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Hang"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Rezgés"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-hy/strings.xml b/packages/SoundPicker/res/values-hy/strings.xml
index d57345c..da8934f 100644
--- a/packages/SoundPicker/res/values-hy/strings.xml
+++ b/packages/SoundPicker/res/values-hy/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Հնարավոր չէ հատուկ զանգերանգ ավելացնել"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Հնարավոր չէ ջնջել հատուկ զանգերանգը"</string>
     <string name="app_label" msgid="3091611356093417332">"Ձայներ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Ցանկը դատարկ է"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ձայն"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Թրթռոց"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-in/strings.xml b/packages/SoundPicker/res/values-in/strings.xml
index 518a09d..86dce64 100644
--- a/packages/SoundPicker/res/values-in/strings.xml
+++ b/packages/SoundPicker/res/values-in/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Tidak dapat menambahkan nada dering khusus"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Tidak dapat menghapus nada dering khusus"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Daftar ini kosong"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Suara"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Getaran"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-is/strings.xml b/packages/SoundPicker/res/values-is/strings.xml
index 7f05c79..d0fce78 100644
--- a/packages/SoundPicker/res/values-is/strings.xml
+++ b/packages/SoundPicker/res/values-is/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Get ekki bætt sérsniðnum hringitóni við"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Get ekki eytt sérsniðnum hringitóni"</string>
     <string name="app_label" msgid="3091611356093417332">"Hljóð"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Listinn er auður"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Hljóð"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Titringur"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-it/strings.xml b/packages/SoundPicker/res/values-it/strings.xml
index e1d8e19..632cb41 100644
--- a/packages/SoundPicker/res/values-it/strings.xml
+++ b/packages/SoundPicker/res/values-it/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Impossibile aggiungere suoneria personalizzata"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Impossibile eliminare suoneria personalizzata"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"L\'elenco è vuoto"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Suoneria"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrazione"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-iw/strings.xml b/packages/SoundPicker/res/values-iw/strings.xml
index 238370c9..387b140 100644
--- a/packages/SoundPicker/res/values-iw/strings.xml
+++ b/packages/SoundPicker/res/values-iw/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"לא ניתן להוסיף רינגטון מותאם אישית"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"לא ניתן למחוק רינגטון מותאם אישית"</string>
     <string name="app_label" msgid="3091611356093417332">"צלילים"</string>
-    <string name="empty_list" msgid="2871978423955821191">"הרשימה ריקה"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"צליל"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"רטט"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ja/strings.xml b/packages/SoundPicker/res/values-ja/strings.xml
index 408e870..7c2aec6 100644
--- a/packages/SoundPicker/res/values-ja/strings.xml
+++ b/packages/SoundPicker/res/values-ja/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"カスタム着信音を追加できません"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"カスタム着信音を削除できません"</string>
     <string name="app_label" msgid="3091611356093417332">"サウンド"</string>
-    <string name="empty_list" msgid="2871978423955821191">"このリストは空です"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"音"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"バイブレーション"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ka/strings.xml b/packages/SoundPicker/res/values-ka/strings.xml
index 83dfc3c..1cfe240 100644
--- a/packages/SoundPicker/res/values-ka/strings.xml
+++ b/packages/SoundPicker/res/values-ka/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"მორგებული ზარის დამატება შეუძლებელია"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"მორგებული ზარის წაშლა შეუძლებელია"</string>
     <string name="app_label" msgid="3091611356093417332">"ხმები"</string>
-    <string name="empty_list" msgid="2871978423955821191">"სია ცარიელია"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ხმა"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ვიბრაცია"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-kk/strings.xml b/packages/SoundPicker/res/values-kk/strings.xml
index 1815a95..8c4c169 100644
--- a/packages/SoundPicker/res/values-kk/strings.xml
+++ b/packages/SoundPicker/res/values-kk/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Арнаулы рингтонды енгізу мүмкін емес"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Арнаулы рингтонды жою мүмкін емес"</string>
     <string name="app_label" msgid="3091611356093417332">"Дыбыстар"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Тізім бос."</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Дыбыс"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Діріл"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-km/strings.xml b/packages/SoundPicker/res/values-km/strings.xml
index 6ae048f..a334429 100644
--- a/packages/SoundPicker/res/values-km/strings.xml
+++ b/packages/SoundPicker/res/values-km/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"មិន​អាច​បន្ថែម​សំឡេង​រោទ៍​ផ្ទាល់ខ្លួន​បាន"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"មិន​អាច​លុប​សំឡេង​រោទ៍​ផ្ទាល់ខ្លួន​បាន​ទេ"</string>
     <string name="app_label" msgid="3091611356093417332">"សំឡេង"</string>
-    <string name="empty_list" msgid="2871978423955821191">"បញ្ជីគឺទទេ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"សំឡេង"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ការញ័រ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-kn/strings.xml b/packages/SoundPicker/res/values-kn/strings.xml
index c528866..da90ccb 100644
--- a/packages/SoundPicker/res/values-kn/strings.xml
+++ b/packages/SoundPicker/res/values-kn/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"ಕಸ್ಟಮ್ ರಿಂಗ್‌ಟೋನ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ಕಸ್ಟಮ್ ರಿಂಗ್‌ಟೋನ್ ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
     <string name="app_label" msgid="3091611356093417332">"ಧ್ವನಿಗಳು"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ಪಟ್ಟಿ ಖಾಲಿಯಾಗಿದೆ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ಧ್ವನಿ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ವೈಬ್ರೇಷನ್"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ko/strings.xml b/packages/SoundPicker/res/values-ko/strings.xml
index bcab6b2..70554d6 100644
--- a/packages/SoundPicker/res/values-ko/strings.xml
+++ b/packages/SoundPicker/res/values-ko/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"맞춤 벨소리를 추가할 수 없습니다."</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"맞춤 벨소리를 삭제할 수 없습니다."</string>
     <string name="app_label" msgid="3091611356093417332">"소리"</string>
-    <string name="empty_list" msgid="2871978423955821191">"목록이 비어 있음"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"소리"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"진동"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ky/strings.xml b/packages/SoundPicker/res/values-ky/strings.xml
index babd8c0..3c95228 100644
--- a/packages/SoundPicker/res/values-ky/strings.xml
+++ b/packages/SoundPicker/res/values-ky/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Жеке рингтон кошулбай жатат"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Жеке рингтон жок кылынбай жатат"</string>
     <string name="app_label" msgid="3091611356093417332">"Үндөр"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Тизме бош"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Үн"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Дирилдөө"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-lo/strings.xml b/packages/SoundPicker/res/values-lo/strings.xml
index 5e496e8..8bcae0d 100644
--- a/packages/SoundPicker/res/values-lo/strings.xml
+++ b/packages/SoundPicker/res/values-lo/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Unable to add custom ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Unable to delete custom ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"ສຽງ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ລາຍຊື່ຫວ່າງເປົ່າ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ສຽງ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ການສັ່ນເຕືອນ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-lt/strings.xml b/packages/SoundPicker/res/values-lt/strings.xml
index c68cc3b..c7ea369 100644
--- a/packages/SoundPicker/res/values-lt/strings.xml
+++ b/packages/SoundPicker/res/values-lt/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nepavyksta pridėti tinkinto skambėjimo tono"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nepavyksta ištrinti tinkinto skambėjimo tono"</string>
     <string name="app_label" msgid="3091611356093417332">"Garsai"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Sąrašas yra tuščias"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Garsas"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibravimas"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-lv/strings.xml b/packages/SoundPicker/res/values-lv/strings.xml
index fab7f8c..2a26289 100644
--- a/packages/SoundPicker/res/values-lv/strings.xml
+++ b/packages/SoundPicker/res/values-lv/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nevar pievienot pielāgotu zvana signālu"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nevar izdzēst pielāgotu zvana signālu"</string>
     <string name="app_label" msgid="3091611356093417332">"Skaņas"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Saraksts ir tukšs"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Skaņa"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrācija"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-mk/strings.xml b/packages/SoundPicker/res/values-mk/strings.xml
index 4f2322a..545d5ed 100644
--- a/packages/SoundPicker/res/values-mk/strings.xml
+++ b/packages/SoundPicker/res/values-mk/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Не може да се додаде приспособена мелодија"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Не може да се избрише приспособена мелодија"</string>
     <string name="app_label" msgid="3091611356093417332">"Звуци"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Списокот е празен"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Звук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вибрации"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ml/strings.xml b/packages/SoundPicker/res/values-ml/strings.xml
index 16cf725..21da8e8 100644
--- a/packages/SoundPicker/res/values-ml/strings.xml
+++ b/packages/SoundPicker/res/values-ml/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"ഇഷ്ടാനുസൃത റിംഗ്‌ടോൺ ചേർക്കാനാവില്ല"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ഇഷ്ടാനുസൃത റിംഗ്‌ടോൺ ഇല്ലാതാക്കാനാവില്ല"</string>
     <string name="app_label" msgid="3091611356093417332">"ശബ്‌ദങ്ങൾ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ലിസ്‌റ്റിൽ ഒന്നുമില്ല"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ശബ്‌ദം"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"വൈബ്രേഷൻ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-mn/strings.xml b/packages/SoundPicker/res/values-mn/strings.xml
index 6215a41..15f7d12 100644
--- a/packages/SoundPicker/res/values-mn/strings.xml
+++ b/packages/SoundPicker/res/values-mn/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Захиалгат хонхны ая нэмэх боломжгүй"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Захиалгат хонхны ая устгах боломжгүй"</string>
     <string name="app_label" msgid="3091611356093417332">"Дуу чимээ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Жагсаалт хоосон байна"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Дуу"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Чичиргээ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-mr/strings.xml b/packages/SoundPicker/res/values-mr/strings.xml
index fe2fe12..3ddb991 100644
--- a/packages/SoundPicker/res/values-mr/strings.xml
+++ b/packages/SoundPicker/res/values-mr/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"कस्टम रिंगटोन जोडण्यात अक्षम"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"कस्टम रिंगटोन हटविण्यात अक्षम"</string>
     <string name="app_label" msgid="3091611356093417332">"आवाज"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ही सूची रिकामी आहे"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"आवाज"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"व्हायब्रेशन"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ms/strings.xml b/packages/SoundPicker/res/values-ms/strings.xml
index 5788f18..9d87d72 100644
--- a/packages/SoundPicker/res/values-ms/strings.xml
+++ b/packages/SoundPicker/res/values-ms/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Tidak dapat menambah nada dering tersuai"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Tidak dapat memadamkan nada dering tersuai"</string>
     <string name="app_label" msgid="3091611356093417332">"Bunyi"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Senarai ini kosong"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Bunyi"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Getaran"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-my/strings.xml b/packages/SoundPicker/res/values-my/strings.xml
index 0a1a4cf..62163e9 100644
--- a/packages/SoundPicker/res/values-my/strings.xml
+++ b/packages/SoundPicker/res/values-my/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"စိတ်ကြိုက်ဖုန်းမြည်သံကို ထည့်သွင်း၍မရပါ"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"စိတ်ကြိုက်ဖုန်းမြည်သံကို ဖျက်၍မရပါ"</string>
     <string name="app_label" msgid="3091611356093417332">"အသံများ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ဤစာရင်းတွင် မည်သည့်အရာမျှမရှိပါ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"အသံ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"တုန်ခါမှု"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-nb/strings.xml b/packages/SoundPicker/res/values-nb/strings.xml
index c315801..e4e259a 100644
--- a/packages/SoundPicker/res/values-nb/strings.xml
+++ b/packages/SoundPicker/res/values-nb/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Kan ikke legge til egendefinert ringelyd"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Kan ikke slette egendefinert ringelyd"</string>
     <string name="app_label" msgid="3091611356093417332">"Lyder"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Listen er tom"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Lyd"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrering"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ne/strings.xml b/packages/SoundPicker/res/values-ne/strings.xml
index b95b70c..0a2bceb 100644
--- a/packages/SoundPicker/res/values-ne/strings.xml
+++ b/packages/SoundPicker/res/values-ne/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"आफू अनुकूल रिङटोन थप्न सकिएन"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"आफू अनुकूल रिङटोनलाई मेट्न सकिएन"</string>
     <string name="app_label" msgid="3091611356093417332">"ध्वनिहरू"</string>
-    <string name="empty_list" msgid="2871978423955821191">"यो सूची खाली छ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ध्वनि"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"भाइब्रेसन"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-nl/strings.xml b/packages/SoundPicker/res/values-nl/strings.xml
index 192431b..5b6fb70 100644
--- a/packages/SoundPicker/res/values-nl/strings.xml
+++ b/packages/SoundPicker/res/values-nl/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Toevoegen van aangepaste ringtone is mislukt"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Verwijderen van aangepaste ringtone is mislukt"</string>
     <string name="app_label" msgid="3091611356093417332">"Geluiden"</string>
-    <string name="empty_list" msgid="2871978423955821191">"De lijst is leeg"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Geluid"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Trillen"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-or/strings.xml b/packages/SoundPicker/res/values-or/strings.xml
index 5d82039..45ce594 100644
--- a/packages/SoundPicker/res/values-or/strings.xml
+++ b/packages/SoundPicker/res/values-or/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"କଷ୍ଟମ୍‍ ରିଙ୍ଗଟୋନ୍‍ ଯୋଡ଼ିପାରିବ ନାହିଁ"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"କଷ୍ଟମ୍‍ ରିଙ୍ଗଟୋନ୍‍ ଡିଲିଟ୍‍ କରିପାରିବ ନାହିଁ"</string>
     <string name="app_label" msgid="3091611356093417332">"ସାଉଣ୍ଡ"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ତାଲିକା ଖାଲି ଅଛି"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ସାଉଣ୍ଡ"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ଭାଇବ୍ରେସନ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-pa/strings.xml b/packages/SoundPicker/res/values-pa/strings.xml
index 63ecb9d..1e62f64 100644
--- a/packages/SoundPicker/res/values-pa/strings.xml
+++ b/packages/SoundPicker/res/values-pa/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"ਵਿਉਂਤੀ ਰਿੰਗਟੋਨ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੇ ਅਯੋਗ"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ਵਿਉਂਤੀ ਰਿੰਗਟੋਨ ਨੂੰ ਮਿਟਾਉਣ ਦੇ ਅਯੋਗ"</string>
     <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ਇਹ ਸੂਚੀ ਖਾਲੀ ਹੈ"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ਅਵਾਜ਼"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"ਥਰਥਰਾਹਟ"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-pl/strings.xml b/packages/SoundPicker/res/values-pl/strings.xml
index 310f40f..1b3b5c4 100644
--- a/packages/SoundPicker/res/values-pl/strings.xml
+++ b/packages/SoundPicker/res/values-pl/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nie można dodać dzwonka niestandardowego"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nie można usunąć dzwonka niestandardowego"</string>
     <string name="app_label" msgid="3091611356093417332">"Dźwięki"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista jest pusta"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Dźwięk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Wibracje"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-pt-rBR/strings.xml b/packages/SoundPicker/res/values-pt-rBR/strings.xml
index 9f58ca0..7b545e1 100644
--- a/packages/SoundPicker/res/values-pt-rBR/strings.xml
+++ b/packages/SoundPicker/res/values-pt-rBR/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível excluir o toque personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"A lista está vazia"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Som"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibração"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-pt-rPT/strings.xml b/packages/SoundPicker/res/values-pt-rPT/strings.xml
index fd4e69f..5d742f1 100644
--- a/packages/SoundPicker/res/values-pt-rPT/strings.xml
+++ b/packages/SoundPicker/res/values-pt-rPT/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível eliminar o toque personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"A lista está vazia"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Som"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibração"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-pt/strings.xml b/packages/SoundPicker/res/values-pt/strings.xml
index 9f58ca0..7b545e1 100644
--- a/packages/SoundPicker/res/values-pt/strings.xml
+++ b/packages/SoundPicker/res/values-pt/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Não foi possível adicionar o toque personalizado"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Não foi possível excluir o toque personalizado"</string>
     <string name="app_label" msgid="3091611356093417332">"Sons"</string>
-    <string name="empty_list" msgid="2871978423955821191">"A lista está vazia"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Som"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibração"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ro/strings.xml b/packages/SoundPicker/res/values-ro/strings.xml
index 08d937c..58b5aeb 100644
--- a/packages/SoundPicker/res/values-ro/strings.xml
+++ b/packages/SoundPicker/res/values-ro/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nu se poate adăuga tonul de sonerie personalizat"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nu se poate șterge tonul de sonerie personalizat"</string>
     <string name="app_label" msgid="3091611356093417332">"Sunete"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista este goală"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sunet"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrație"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ru/strings.xml b/packages/SoundPicker/res/values-ru/strings.xml
index be5495a..0d48ac1 100644
--- a/packages/SoundPicker/res/values-ru/strings.xml
+++ b/packages/SoundPicker/res/values-ru/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Не удалось добавить рингтон"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Не удалось удалить рингтон"</string>
     <string name="app_label" msgid="3091611356093417332">"Звуки"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Список пуст"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Звук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вибрация"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-si/strings.xml b/packages/SoundPicker/res/values-si/strings.xml
index 6ba86cb..1872b6b 100644
--- a/packages/SoundPicker/res/values-si/strings.xml
+++ b/packages/SoundPicker/res/values-si/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"අභිරුචි නාද රිද්මය එක් කළ නොහැකිය"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"අභිරුචි නාද රිද්මය මැකිය නොහැකිය"</string>
     <string name="app_label" msgid="3091611356093417332">"ශබ්ද"</string>
-    <string name="empty_list" msgid="2871978423955821191">"ලැයිස්තුව හිස් ය"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ශබ්දය"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"කම්පනය"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sk/strings.xml b/packages/SoundPicker/res/values-sk/strings.xml
index 8f54350..8ff6d12 100644
--- a/packages/SoundPicker/res/values-sk/strings.xml
+++ b/packages/SoundPicker/res/values-sk/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nepodarilo sa pridať vlastný tón zvonenia"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nepodarilo sa odstrániť vlastný tón zvonenia"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvuky"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Zoznam je prázdny"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvuk"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibrácie"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sl/strings.xml b/packages/SoundPicker/res/values-sl/strings.xml
index 1a818b2..77a2a2c 100644
--- a/packages/SoundPicker/res/values-sl/strings.xml
+++ b/packages/SoundPicker/res/values-sl/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Tona zvonjenja po meri ni mogoče dodati"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Tona zvonjenja po meri ni mogoče izbrisati"</string>
     <string name="app_label" msgid="3091611356093417332">"Zvoki"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Seznam je prazen"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Zvok"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibriranje"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sq/strings.xml b/packages/SoundPicker/res/values-sq/strings.xml
index 4c497bb..e35dd71 100644
--- a/packages/SoundPicker/res/values-sq/strings.xml
+++ b/packages/SoundPicker/res/values-sq/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Nuk mund të shtojë ton zileje të personalizuar"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Nuk mund të fshijë ton zileje të personalizuar"</string>
     <string name="app_label" msgid="3091611356093417332">"Tingujt"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Lista është bosh"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Me tingull"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Me dridhje"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sr/strings.xml b/packages/SoundPicker/res/values-sr/strings.xml
index 2ec1f17..bc573f5 100644
--- a/packages/SoundPicker/res/values-sr/strings.xml
+++ b/packages/SoundPicker/res/values-sr/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Додавање прилагођене мелодије звона није успело"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Брисање прилагођене мелодије звона није успело"</string>
     <string name="app_label" msgid="3091611356093417332">"Звукови"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Листа је празна"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Звук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вибрирање"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sv/strings.xml b/packages/SoundPicker/res/values-sv/strings.xml
index cb1cd3a..c1dd1c2 100644
--- a/packages/SoundPicker/res/values-sv/strings.xml
+++ b/packages/SoundPicker/res/values-sv/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Det gick inte att lägga till en egen ringsignal"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Det gick inte att radera den egna ringsignalen"</string>
     <string name="app_label" msgid="3091611356093417332">"Ljud"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Listan är tom"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ljud"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Vibration"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-sw/strings.xml b/packages/SoundPicker/res/values-sw/strings.xml
index 8fd6d58..b023450 100644
--- a/packages/SoundPicker/res/values-sw/strings.xml
+++ b/packages/SoundPicker/res/values-sw/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Imeshindwa kuongeza mlio maalum wa simu"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Imeshindwa kufuta mlio maalum wa simu"</string>
     <string name="app_label" msgid="3091611356093417332">"Sauti"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Orodha hii haina chochote"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Sauti"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Mtetemo"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ta/strings.xml b/packages/SoundPicker/res/values-ta/strings.xml
index 692e58a..38e45b7 100644
--- a/packages/SoundPicker/res/values-ta/strings.xml
+++ b/packages/SoundPicker/res/values-ta/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"பிரத்தியேக ரிங்டோனைச் சேர்க்க முடியவில்லை"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"பிரத்தியேக ரிங்டோனை நீக்க முடியவில்லை"</string>
     <string name="app_label" msgid="3091611356093417332">"ஒலிகள்"</string>
-    <string name="empty_list" msgid="2871978423955821191">"பட்டியல் காலியாக உள்ளது"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"ஒலி"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"அதிர்வு"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-te/strings.xml b/packages/SoundPicker/res/values-te/strings.xml
index ce13e53..2d03ac0 100644
--- a/packages/SoundPicker/res/values-te/strings.xml
+++ b/packages/SoundPicker/res/values-te/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"అనుకూల రింగ్‌టోన్‌ను జోడించలేకపోయింది"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"అనుకూల రింగ్‌టోన్‌ను తొలగించలేకపోయింది"</string>
     <string name="app_label" msgid="3091611356093417332">"ధ్వనులు"</string>
-    <string name="empty_list" msgid="2871978423955821191">"మీ లిస్ట్ ఖాళీగా ఉంది"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"సౌండ్"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"వైబ్రేషన్"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-th/strings.xml b/packages/SoundPicker/res/values-th/strings.xml
index d5dc9b7..cc2e43f 100644
--- a/packages/SoundPicker/res/values-th/strings.xml
+++ b/packages/SoundPicker/res/values-th/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"ไม่สามารถเพิ่มเสียงเรียกเข้าที่กำหนดเอง"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"ไม่สามารถลบเสียงเรียกเข้าที่กำหนดเอง"</string>
     <string name="app_label" msgid="3091611356093417332">"เสียง"</string>
-    <string name="empty_list" msgid="2871978423955821191">"รายการว่างเปล่า"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"เสียง"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"การสั่น"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-tl/strings.xml b/packages/SoundPicker/res/values-tl/strings.xml
index 4e3bf7e..c0c1712 100644
--- a/packages/SoundPicker/res/values-tl/strings.xml
+++ b/packages/SoundPicker/res/values-tl/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Hindi maidagdag ang custom na ringtone"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Hindi ma-delete ang custom na ringtone"</string>
     <string name="app_label" msgid="3091611356093417332">"Mga Tunog"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Walang laman ang listahan"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Tunog"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Pag-vibrate"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-tr/strings.xml b/packages/SoundPicker/res/values-tr/strings.xml
index 51ac541..955c23f 100644
--- a/packages/SoundPicker/res/values-tr/strings.xml
+++ b/packages/SoundPicker/res/values-tr/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Özel zil sesi eklenemiyor"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Özel zil sesi silinemiyor"</string>
     <string name="app_label" msgid="3091611356093417332">"Sesler"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Liste boş"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Ses"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Titreşim"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-uk/strings.xml b/packages/SoundPicker/res/values-uk/strings.xml
index a905b95..42dbfb0 100644
--- a/packages/SoundPicker/res/values-uk/strings.xml
+++ b/packages/SoundPicker/res/values-uk/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Не вдалося додати користувацький сигнал дзвінка"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Не вдалося видалити користувацький сигнал дзвінка"</string>
     <string name="app_label" msgid="3091611356093417332">"Звуки"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Список пустий"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Звук"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Вібрація"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-ur/strings.xml b/packages/SoundPicker/res/values-ur/strings.xml
index 9cae118..58141d6 100644
--- a/packages/SoundPicker/res/values-ur/strings.xml
+++ b/packages/SoundPicker/res/values-ur/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"حسب ضرورت رنگ ٹون شامل کرنے سے قاصر ہے"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"حسب ضرورت رنگ ٹون حذف کرنے سے قاصر ہے"</string>
     <string name="app_label" msgid="3091611356093417332">"آوازیں"</string>
-    <string name="empty_list" msgid="2871978423955821191">"فہرست خالی ہے"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"آواز"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"وائبریشن"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-uz/strings.xml b/packages/SoundPicker/res/values-uz/strings.xml
index e6231f2..c39db5f 100644
--- a/packages/SoundPicker/res/values-uz/strings.xml
+++ b/packages/SoundPicker/res/values-uz/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Maxsus rington qo‘shib bo‘lmadi"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Maxsus ringtonni o‘chirib bo‘lmadi"</string>
     <string name="app_label" msgid="3091611356093417332">"Tovushlar"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Roʻyxat boʻsh"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Tovush"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Tebranish"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-vi/strings.xml b/packages/SoundPicker/res/values-vi/strings.xml
index 070ac16..bed0e96 100644
--- a/packages/SoundPicker/res/values-vi/strings.xml
+++ b/packages/SoundPicker/res/values-vi/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Không thể thêm nhạc chuông tùy chỉnh"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Không thể xóa nhạc chuông tùy chỉnh"</string>
     <string name="app_label" msgid="3091611356093417332">"Âm thanh"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Danh sách này đang trống"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Âm thanh"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Rung"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-zh-rCN/strings.xml b/packages/SoundPicker/res/values-zh-rCN/strings.xml
index 0420fc9..864aaae 100644
--- a/packages/SoundPicker/res/values-zh-rCN/strings.xml
+++ b/packages/SoundPicker/res/values-zh-rCN/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"无法添加自定义铃声"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"无法删除自定义铃声"</string>
     <string name="app_label" msgid="3091611356093417332">"声音"</string>
-    <string name="empty_list" msgid="2871978423955821191">"列表为空"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"声音"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"振动"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-zh-rHK/strings.xml b/packages/SoundPicker/res/values-zh-rHK/strings.xml
index 60d9a52..4cde32d 100644
--- a/packages/SoundPicker/res/values-zh-rHK/strings.xml
+++ b/packages/SoundPicker/res/values-zh-rHK/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"無法加入自訂鈴聲"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"無法刪除自訂鈴聲"</string>
     <string name="app_label" msgid="3091611356093417332">"音效"</string>
-    <string name="empty_list" msgid="2871978423955821191">"清單中沒有內容"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"音效"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"震動"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-zh-rTW/strings.xml b/packages/SoundPicker/res/values-zh-rTW/strings.xml
index c173c0a..df8a66a 100644
--- a/packages/SoundPicker/res/values-zh-rTW/strings.xml
+++ b/packages/SoundPicker/res/values-zh-rTW/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"無法新增自訂鈴聲"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"無法刪除自訂鈴聲"</string>
     <string name="app_label" msgid="3091611356093417332">"音效"</string>
-    <string name="empty_list" msgid="2871978423955821191">"清單中沒有任何項目"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"音效"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"震動"</string>
 </resources>
diff --git a/packages/SoundPicker/res/values-zu/strings.xml b/packages/SoundPicker/res/values-zu/strings.xml
index 978e925..29a8ffe 100644
--- a/packages/SoundPicker/res/values-zu/strings.xml
+++ b/packages/SoundPicker/res/values-zu/strings.xml
@@ -26,7 +26,4 @@
     <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Ayikwazi ukwengeza ithoni yokukhala yangokwezifiso"</string>
     <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Ayikwazi ukususa ithoni yokukhala yangokwezifiso"</string>
     <string name="app_label" msgid="3091611356093417332">"Imisindo"</string>
-    <string name="empty_list" msgid="2871978423955821191">"Uhlu alunalutho"</string>
-    <string name="sound_page_title" msgid="2143312098775103522">"Umsindo"</string>
-    <string name="vibration_page_title" msgid="6519501440349124677">"Ukudlidliza"</string>
 </resources>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9d3200d..e6a82e8 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -214,6 +214,7 @@
 
     lint: {
         extra_check_modules: ["SystemUILintChecker"],
+        warning_checks: ["MissingApacheLicenseDetector"],
     },
 }
 
@@ -254,7 +255,6 @@
     srcs: [
         /* Keyguard converted tests */
         // data
-        "tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt",
         "tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt",
         "tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt",
         "tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt",
@@ -402,10 +402,19 @@
         "tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt",
         "tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt",
         "tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt",
+
     ],
     path: "tests/src",
 }
 
+filegroup {
+    name: "SystemUI-tests-multivalent",
+    srcs: [
+        "multivalentTests/src/**/*.kt",
+    ],
+    path: "multivalentTests/src",
+}
+
 java_library {
     name: "SystemUI-tests-concurrency",
     srcs: [
@@ -494,6 +503,7 @@
         "src/**/*.java",
         "src/**/I*.aidl",
         ":ReleaseJavaFiles",
+        ":SystemUI-tests-multivalent",
         ":SystemUI-tests-utils",
     ],
     static_libs: [
@@ -572,6 +582,7 @@
         ":SystemUI-tests-utils",
         ":SystemUI-test-fakes",
         ":SystemUI-tests-robolectric-pilots",
+        ":SystemUI-tests-multivalent",
     ],
     static_libs: [
         "androidx.test.uiautomator_uiautomator",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hy/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hy/strings.xml
index e06787f..66e37a1 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-hy/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-hy/strings.xml
@@ -10,7 +10,7 @@
     <string name="power_utterance" msgid="7444296686402104807">"Սնուցման կոճակի ընտրանքներ"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"Վերջին հավելվածներ"</string>
     <string name="lockscreen_label" msgid="648347953557887087">"Կողպէկրան"</string>
-    <string name="quick_settings_label" msgid="2999117381487601865">"Արագ\\nկարգավորումներ"</string>
+    <string name="quick_settings_label" msgid="2999117381487601865">"Արագ կարգա­վորումներ"</string>
     <string name="notifications_label" msgid="6829741046963013567">"Ծանուցումներ"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Սքրինշոթ"</string>
     <string name="screenshot_utterance" msgid="1430760563401895074">"Ստանալ սքրինշոթը"</string>
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
new file mode 100644
index 0000000..46125be
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.ide.common.blame.SourcePosition
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import java.time.Year
+import org.jetbrains.uast.UComment
+import org.jetbrains.uast.UFile
+
+/**
+ * Checks if every AOSP Java/Kotlin source code file is starting with Apache license information.
+ */
+class MissingApacheLicenseDetector : Detector(), SourceCodeScanner {
+
+    override fun getApplicableUastTypes() = listOf(UFile::class.java)
+
+    override fun createUastHandler(context: JavaContext): UElementHandler? {
+        return object : UElementHandler() {
+            override fun visitFile(node: UFile) {
+                val firstComment = node.allCommentsInFile.firstOrNull()
+                // Normally we don't need to explicitly handle suppressing case and just return
+                // error as usual with indicating node and lint will ignore it for us. But here
+                // suppressing will be applied on top of comment that doesn't exist so we don't have
+                // node to return - it's a bit of corner case
+                if (firstComment != null && firstComment.isSuppressingComment()) {
+                    return
+                }
+                if (firstComment == null || !firstComment.isLicenseComment()) {
+                    val firstLineOfFile =
+                        Location.create(
+                            context.file,
+                            SourcePosition(/* lineNumber= */ 1, /* column= */ 1, /* offset= */ 0)
+                        )
+                    context.report(
+                        issue = ISSUE,
+                        location = firstLineOfFile,
+                        message =
+                            "License header is missing\n" +
+                                "Please add the following copyright and license header to the" +
+                                " beginning of the file:\n\n" +
+                                copyrightHeader
+                    )
+                }
+            }
+        }
+    }
+
+    private fun UComment.isSuppressingComment(): Boolean {
+        val suppressingComment =
+            "//noinspection ${MissingApacheLicenseDetector::class.java.simpleName}"
+        return text.contains(suppressingComment)
+    }
+
+    private fun UComment.isLicenseComment(): Boolean {
+        // We probably don't want to compare full copyright header in case there are some small
+        // discrepancies in already existing files, e.g. year. We could do regexp but it should be
+        // good enough if this detector deals with missing
+        // license header instead of incorrect license header
+        return text.contains("Apache License")
+    }
+
+    private val copyrightHeader: String
+        get() =
+            """
+            /*
+             * Copyright (C) ${Year.now().value} The Android Open Source Project
+             *
+             * Licensed under the Apache License, Version 2.0 (the "License");
+             * you may not use this file except in compliance with the License.
+             * You may obtain a copy of the License at
+             *
+             *     http://www.apache.org/licenses/LICENSE-2.0
+             *
+             * Unless required by applicable law or agreed to in writing, software
+             * distributed under the License is distributed on an "AS IS" BASIS,
+             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+             * See the License for the specific language governing permissions and
+             * limitations under the License.
+             */
+            """
+                .trimIndent()
+                .trim()
+
+    companion object {
+        @JvmField
+        val ISSUE: Issue =
+            Issue.create(
+                id = "MissingApacheLicenseDetector",
+                briefDescription = "File is missing Apache license information",
+                explanation =
+                    """
+                        Every source code file should have copyright and license information \
+                        attached at the beginning.""",
+                category = Category.COMPLIANCE,
+                priority = 8,
+                // ignored by default and then explicitly overridden in SysUI's soong configuration
+                severity = Severity.IGNORE,
+                implementation =
+                    Implementation(MissingApacheLicenseDetector::class.java, Scope.JAVA_FILE_SCOPE),
+            )
+    }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 520c888..e09aa42 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -42,6 +42,7 @@
                 StaticSettingsProviderDetector.ISSUE,
                 DemotingTestWithoutBugDetector.ISSUE,
                 TestFunctionNameViolationDetector.ISSUE,
+                MissingApacheLicenseDetector.ISSUE,
             )
 
     override val api: Int
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
new file mode 100644
index 0000000..78e133f
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *            http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestMode
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import java.time.Year
+import org.junit.Test
+
+class MissingApacheLicenseDetectorTest : SystemUILintDetectorTest() {
+    override fun getDetector(): Detector {
+        return MissingApacheLicenseDetector()
+    }
+
+    override fun getIssues(): List<Issue> {
+        return listOf(
+            MissingApacheLicenseDetector.ISSUE,
+        )
+    }
+
+    @Test
+    fun testHasCopyright() {
+        lint()
+            .files(
+                kotlin(
+                    """
+                    /*
+                     * Copyright (C) ${Year.now().value} The Android Open Source Project
+                     *
+                     * Licensed under the Apache License, Version 2.0 (the "License");
+                     * you may not use this file except in compliance with the License.
+                     * You may obtain a copy of the License at
+                     *
+                     *     http://www.apache.org/licenses/LICENSE-2.0
+                     *
+                     * Unless required by applicable law or agreed to in writing, software
+                     * distributed under the License is distributed on an "AS IS" BASIS,
+                     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+                     * See the License for the specific language governing permissions and
+                     * limitations under the License.
+                     */
+
+                    package test.pkg.name
+
+                    class MyTest
+                    """
+                        .trimIndent()
+                )
+            )
+            .issues(MissingApacheLicenseDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun testDoesntHaveCopyright() {
+        lint()
+            .files(
+                kotlin(
+                    """
+                    package test.pkg.name
+
+                    class MyTest
+                    """
+                        .trimIndent()
+                )
+            )
+            // skipping mode SUPPRESSIBLE because lint tries to add @Suppress to class which
+            // probably doesn't make much sense for license header (which is far above it) and for
+            // kotlin files that can have several classes. If someone really wants to omit header
+            // they can do it with //noinspection
+            .skipTestModes(TestMode.SUPPRESSIBLE)
+            .issues(MissingApacheLicenseDetector.ISSUE)
+            .run()
+            .expectContains("License header is missing")
+    }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
new file mode 100644
index 0000000..d005413
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
@@ -0,0 +1,20 @@
+package com.android.compose.animation.scene
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import kotlinx.coroutines.CoroutineScope
+
+interface GestureHandler {
+    val draggable: DraggableHandler
+    val nestedScroll: NestedScrollHandler
+}
+
+interface DraggableHandler {
+    suspend fun onDragStarted(coroutineScope: CoroutineScope, startedPosition: Offset)
+    fun onDelta(pixels: Float)
+    suspend fun onDragStopped(coroutineScope: CoroutineScope, velocity: Float)
+}
+
+interface NestedScrollHandler {
+    val connection: NestedScrollConnection
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index 3fd6828..9c799b28 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -16,6 +16,7 @@
 
 package com.android.compose.animation.scene
 
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
@@ -100,3 +101,19 @@
         MovableElement(layoutImpl, scene, key, modifier, content)
     }
 }
+
+/** The destination scene when swiping up or left from [upOrLeft]. */
+internal fun Scene.upOrLeft(orientation: Orientation): SceneKey? {
+    return when (orientation) {
+        Orientation.Vertical -> userActions[Swipe.Up]
+        Orientation.Horizontal -> userActions[Swipe.Left]
+    }
+}
+
+/** The destination scene when swiping down or right from [downOrRight]. */
+internal fun Scene.downOrRight(orientation: Orientation): SceneKey? {
+    return when (orientation) {
+        Orientation.Vertical -> userActions[Swipe.Down]
+        Orientation.Horizontal -> userActions[Swipe.Right]
+    }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index 4952270..a40b299 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -17,6 +17,7 @@
 package com.android.compose.animation.scene
 
 import androidx.activity.compose.BackHandler
+import androidx.annotation.VisibleForTesting
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
@@ -39,7 +40,8 @@
 import com.android.compose.ui.util.fastForEach
 import kotlinx.coroutines.channels.Channel
 
-internal class SceneTransitionLayoutImpl(
+@VisibleForTesting
+class SceneTransitionLayoutImpl(
     onChangeScene: (SceneKey) -> Unit,
     builder: SceneTransitionLayoutScope.() -> Unit,
     transitions: SceneTransitions,
@@ -60,7 +62,7 @@
      * The size of this layout. Note that this could be [IntSize.Zero] if this layour does not have
      * any scene configured or right before the first measure pass of the layout.
      */
-    internal var size by mutableStateOf(IntSize.Zero)
+    @VisibleForTesting var size by mutableStateOf(IntSize.Zero)
 
     init {
         setScenes(builder)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index 1cbfe30..d70a248 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -16,10 +16,11 @@
 
 package com.android.compose.animation.scene
 
+import android.util.Log
+import androidx.annotation.VisibleForTesting
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.DraggableState
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.draggable
 import androidx.compose.foundation.gestures.rememberDraggableState
@@ -34,10 +35,9 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.nestedscroll.nestedScroll
-import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.Velocity
 import androidx.compose.ui.unit.dp
-import com.android.compose.nestedscroll.PriorityPostNestedScrollConnection
+import com.android.compose.nestedscroll.PriorityNestedScrollConnection
 import kotlin.math.absoluteValue
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
@@ -51,417 +51,378 @@
     layoutImpl: SceneTransitionLayoutImpl,
     orientation: Orientation,
 ): Modifier {
-    val state = layoutImpl.state.transitionState
-    val currentScene = layoutImpl.scene(state.currentScene)
-    val transition = remember {
-        // Note that the currentScene here does not matter, it's only used for initializing the
-        // transition and will be replaced when a drag event starts.
-        SwipeTransition(initialScene = currentScene)
-    }
+    val gestureHandler = rememberSceneGestureHandler(layoutImpl, orientation)
 
-    val enabled = state == transition || currentScene.shouldEnableSwipes(orientation)
+    /** Whether swipe should be enabled in the given [orientation]. */
+    fun Scene.shouldEnableSwipes(orientation: Orientation): Boolean =
+        upOrLeft(orientation) != null || downOrRight(orientation) != null
 
-    // Immediately start the drag if this our [transition] is currently animating to a scene (i.e.
-    // the user released their input pointer after swiping in this orientation) and the user can't
-    // swipe in the other direction.
-    val startDragImmediately =
-        state == transition &&
-            transition.isAnimatingOffset &&
-            !currentScene.shouldEnableSwipes(orientation.opposite())
-
-    // The velocity threshold at which the intent of the user is to swipe up or down. It is the same
-    // as SwipeableV2Defaults.VelocityThreshold.
-    val velocityThreshold = with(LocalDensity.current) { 125.dp.toPx() }
-
-    // The positional threshold at which the intent of the user is to swipe to the next scene. It is
-    // the same as SwipeableV2Defaults.PositionalThreshold.
-    val positionalThreshold = with(LocalDensity.current) { 56.dp.toPx() }
-
-    val draggableState = rememberDraggableState { delta ->
-        onDrag(layoutImpl, transition, orientation, delta)
-    }
-
-    return nestedScroll(
-            connection =
-                rememberSwipeToSceneNestedScrollConnection(
-                    orientation = orientation,
-                    coroutineScope = rememberCoroutineScope(),
-                    draggableState = draggableState,
-                    transition = transition,
-                    layoutImpl = layoutImpl,
-                    velocityThreshold = velocityThreshold,
-                    positionalThreshold = positionalThreshold
-                ),
+    val currentScene = gestureHandler.currentScene
+    val canSwipe = currentScene.shouldEnableSwipes(orientation)
+    val canOppositeSwipe =
+        currentScene.shouldEnableSwipes(
+            when (orientation) {
+                Orientation.Vertical -> Orientation.Horizontal
+                Orientation.Horizontal -> Orientation.Vertical
+            }
         )
+
+    return nestedScroll(connection = gestureHandler.nestedScroll.connection)
         .draggable(
-            state = draggableState,
+            state = rememberDraggableState(onDelta = gestureHandler.draggable::onDelta),
             orientation = orientation,
-            enabled = enabled,
-            startDragImmediately = startDragImmediately,
-            onDragStarted = { onDragStarted(layoutImpl, transition, orientation) },
-            onDragStopped = { velocity ->
-                onDragStopped(
-                    layoutImpl = layoutImpl,
-                    transition = transition,
-                    velocity = velocity,
-                    velocityThreshold = velocityThreshold,
-                    positionalThreshold = positionalThreshold,
-                )
-            },
+            enabled = gestureHandler.isDrivingTransition || canSwipe,
+            // Immediately start the drag if this our [transition] is currently animating to a scene
+            // (i.e. the user released their input pointer after swiping in this orientation) and
+            // the user can't swipe in the other direction.
+            startDragImmediately =
+                gestureHandler.isDrivingTransition &&
+                    gestureHandler.isAnimatingOffset &&
+                    !canOppositeSwipe,
+            onDragStarted = gestureHandler.draggable::onDragStarted,
+            onDragStopped = gestureHandler.draggable::onDragStopped,
         )
 }
 
-private class SwipeTransition(initialScene: Scene) : TransitionState.Transition {
-    var _currentScene by mutableStateOf(initialScene)
-    override val currentScene: SceneKey
-        get() = _currentScene.key
+@Composable
+private fun rememberSceneGestureHandler(
+    layoutImpl: SceneTransitionLayoutImpl,
+    orientation: Orientation,
+): SceneGestureHandler {
+    val coroutineScope = rememberCoroutineScope()
 
-    var _fromScene by mutableStateOf(initialScene)
-    override val fromScene: SceneKey
-        get() = _fromScene.key
+    val gestureHandler =
+        remember(layoutImpl, orientation, coroutineScope) {
+            SceneGestureHandler(layoutImpl, orientation, coroutineScope)
+        }
 
-    var _toScene by mutableStateOf(initialScene)
-    override val toScene: SceneKey
-        get() = _toScene.key
+    // Make sure we reset the scroll connection when this handler is removed from composition
+    val connection = gestureHandler.nestedScroll.connection
+    DisposableEffect(connection) { onDispose { connection.reset() } }
 
-    override val progress: Float
-        get() {
-            val offset = if (isAnimatingOffset) offsetAnimatable.value else dragOffset
-            if (distance == 0f) {
-                // This can happen only if fromScene == toScene.
-                error(
-                    "Transition.progress should be called only when Transition.fromScene != " +
-                        "Transition.toScene"
+    return gestureHandler
+}
+
+@VisibleForTesting
+class SceneGestureHandler(
+    private val layoutImpl: SceneTransitionLayoutImpl,
+    internal val orientation: Orientation,
+    private val coroutineScope: CoroutineScope,
+) : GestureHandler {
+    override val draggable: DraggableHandler = SceneDraggableHandler(this)
+
+    override val nestedScroll: SceneNestedScrollHandler = SceneNestedScrollHandler(this)
+
+    private var transitionState
+        get() = layoutImpl.state.transitionState
+        set(value) {
+            layoutImpl.state.transitionState = value
+        }
+
+    /**
+     * The transition controlled by this gesture handler. It will be set as the [transitionState] in
+     * the [SceneTransitionLayoutImpl] whenever this handler is driving the current transition.
+     *
+     * Note: the initialScene here does not matter, it's only used for initializing the transition
+     * and will be replaced when a drag event starts.
+     */
+    private val swipeTransition = SwipeTransition(initialScene = currentScene)
+
+    internal val currentScene: Scene
+        get() = layoutImpl.scene(transitionState.currentScene)
+
+    @VisibleForTesting
+    val isDrivingTransition
+        get() = transitionState == swipeTransition
+
+    @VisibleForTesting
+    var isAnimatingOffset
+        get() = swipeTransition.isAnimatingOffset
+        private set(value) {
+            swipeTransition.isAnimatingOffset = value
+        }
+
+    internal val swipeTransitionToScene
+        get() = swipeTransition._toScene
+
+    /**
+     * The velocity threshold at which the intent of the user is to swipe up or down. It is the same
+     * as SwipeableV2Defaults.VelocityThreshold.
+     */
+    @VisibleForTesting val velocityThreshold = with(layoutImpl.density) { 125.dp.toPx() }
+
+    /**
+     * The positional threshold at which the intent of the user is to swipe to the next scene. It is
+     * the same as SwipeableV2Defaults.PositionalThreshold.
+     */
+    private val positionalThreshold = with(layoutImpl.density) { 56.dp.toPx() }
+
+    internal fun onDragStarted() {
+        if (isDrivingTransition) {
+            // This [transition] was already driving the animation: simply take over it.
+            // Stop animating and start from where the current offset.
+            swipeTransition.stopOffsetAnimation()
+            return
+        }
+
+        val transition = transitionState
+        if (transition is TransitionState.Transition) {
+            // TODO(b/290184746): Better handle interruptions here if state != idle.
+            Log.w(
+                TAG,
+                "start from TransitionState.Transition is not fully supported: from" +
+                    " ${transition.fromScene} to ${transition.toScene} " +
+                    "(progress ${transition.progress})"
+            )
+        }
+
+        val fromScene = currentScene
+
+        swipeTransition._currentScene = fromScene
+        swipeTransition._fromScene = fromScene
+
+        // We don't know where we are transitioning to yet given that the drag just started, so set
+        // it to fromScene, which will effectively be treated the same as Idle(fromScene).
+        swipeTransition._toScene = fromScene
+
+        swipeTransition.stopOffsetAnimation()
+        swipeTransition.dragOffset = 0f
+
+        // Use the layout size in the swipe orientation for swipe distance.
+        // TODO(b/290184746): Also handle custom distances for transitions. With smaller distances,
+        // we will also have to make sure that we correctly handle overscroll.
+        swipeTransition.absoluteDistance =
+            when (orientation) {
+                Orientation.Horizontal -> layoutImpl.size.width
+                Orientation.Vertical -> layoutImpl.size.height
+            }.toFloat()
+
+        if (swipeTransition.absoluteDistance > 0f) {
+            transitionState = swipeTransition
+        }
+    }
+
+    internal fun onDrag(delta: Float) {
+        if (delta == 0f) return
+
+        swipeTransition.dragOffset += delta
+
+        // First check transition.fromScene should be changed for the case where the user quickly
+        // swiped twice in a row to accelerate the transition and go from A => B then B => C really
+        // fast.
+        maybeHandleAcceleratedSwipe()
+
+        val offset = swipeTransition.dragOffset
+        val fromScene = swipeTransition._fromScene
+
+        // Compute the target scene depending on the current offset.
+        val target = fromScene.findTargetSceneAndDistance(offset)
+
+        if (swipeTransition._toScene.key != target.sceneKey) {
+            swipeTransition._toScene = layoutImpl.scenes.getValue(target.sceneKey)
+        }
+
+        if (swipeTransition._distance != target.distance) {
+            swipeTransition._distance = target.distance
+        }
+    }
+
+    /**
+     * Change fromScene in the case where the user quickly swiped multiple times in the same
+     * direction to accelerate the transition from A => B then B => C.
+     */
+    private fun maybeHandleAcceleratedSwipe() {
+        val toScene = swipeTransition._toScene
+        val fromScene = swipeTransition._fromScene
+
+        // If the swipe was not committed, don't do anything.
+        if (fromScene == toScene || swipeTransition._currentScene != toScene) {
+            return
+        }
+
+        // If the offset is past the distance then let's change fromScene so that the user can swipe
+        // to the next screen or go back to the previous one.
+        val offset = swipeTransition.dragOffset
+        val absoluteDistance = swipeTransition.absoluteDistance
+        if (offset <= -absoluteDistance && fromScene.upOrLeft(orientation) == toScene.key) {
+            swipeTransition.dragOffset += absoluteDistance
+            swipeTransition._fromScene = toScene
+        } else if (
+            offset >= absoluteDistance && fromScene.downOrRight(orientation) == toScene.key
+        ) {
+            swipeTransition.dragOffset -= absoluteDistance
+            swipeTransition._fromScene = toScene
+        }
+
+        // Important note: toScene and distance will be updated right after this function is called,
+        // using fromScene and dragOffset.
+    }
+
+    private class TargetScene(
+        val sceneKey: SceneKey,
+        val distance: Float,
+    )
+
+    private fun Scene.findTargetSceneAndDistance(directionOffset: Float): TargetScene {
+        val maxDistance =
+            when (orientation) {
+                Orientation.Horizontal -> layoutImpl.size.width
+                Orientation.Vertical -> layoutImpl.size.height
+            }.toFloat()
+
+        val upOrLeft = upOrLeft(orientation)
+        val downOrRight = downOrRight(orientation)
+
+        // Compute the target scene depending on the current offset.
+        return when {
+            directionOffset < 0f && upOrLeft != null -> {
+                TargetScene(
+                    sceneKey = upOrLeft,
+                    distance = -maxDistance,
                 )
             }
-            return offset / distance
+            directionOffset > 0f && downOrRight != null -> {
+                TargetScene(
+                    sceneKey = downOrRight,
+                    distance = maxDistance,
+                )
+            }
+            else -> {
+                TargetScene(
+                    sceneKey = key,
+                    distance = 0f,
+                )
+            }
+        }
+    }
+
+    internal fun onDragStopped(velocity: Float, canChangeScene: Boolean) {
+        // The state was changed since the drag started; don't do anything.
+        if (!isDrivingTransition) {
+            return
         }
 
-    override val isUserInputDriven = true
+        fun animateTo(targetScene: Scene, targetOffset: Float) {
+            // If the effective current scene changed, it should be reflected right now in the
+            // current scene state, even before the settle animation is ongoing. That way all the
+            // swipeables and back handlers will be refreshed and the user can for instance quickly
+            // swipe vertically from A => B then horizontally from B => C, or swipe from A => B then
+            // immediately go back B => A.
+            if (targetScene != swipeTransition._currentScene) {
+                swipeTransition._currentScene = targetScene
+                layoutImpl.onChangeScene(targetScene.key)
+            }
 
-    /** The current offset caused by the drag gesture. */
-    var dragOffset by mutableFloatStateOf(0f)
+            animateOffset(
+                initialVelocity = velocity,
+                targetOffset = targetOffset,
+                targetScene = targetScene.key
+            )
+        }
+
+        val fromScene = swipeTransition._fromScene
+        if (canChangeScene) {
+            // If we are halfway between two scenes, we check what the target will be based on the
+            // velocity and offset of the transition, then we launch the animation.
+
+            val toScene = swipeTransition._toScene
+            if (fromScene == toScene) {
+                // We were not animating.
+                transitionState = TransitionState.Idle(fromScene.key)
+                return
+            }
+
+            // Compute the destination scene (and therefore offset) to settle in.
+            val offset = swipeTransition.dragOffset
+            val distance = swipeTransition.distance
+            if (
+                shouldCommitSwipe(
+                    offset,
+                    distance,
+                    velocity,
+                    wasCommitted = swipeTransition._currentScene == toScene,
+                )
+            ) {
+                // Animate to the next scene
+                animateTo(targetScene = toScene, targetOffset = distance)
+            } else {
+                // Animate to the initial scene
+                animateTo(targetScene = fromScene, targetOffset = 0f)
+            }
+        } else {
+            // We are doing an overscroll animation between scenes. In this case, we can also start
+            // from the idle position.
+
+            val startFromIdlePosition = swipeTransition.dragOffset == 0f
+
+            if (startFromIdlePosition) {
+                // If there is a next scene, we start the overscroll animation.
+                val target = fromScene.findTargetSceneAndDistance(velocity)
+                val isValidTarget = target.distance != 0f && target.sceneKey != fromScene.key
+                if (isValidTarget) {
+                    swipeTransition._toScene = layoutImpl.scene(target.sceneKey)
+                    swipeTransition._distance = target.distance
+
+                    animateTo(targetScene = fromScene, targetOffset = 0f)
+                } else {
+                    // We will not animate
+                    transitionState = TransitionState.Idle(fromScene.key)
+                }
+            } else {
+                // We were between two scenes: animate to the initial scene.
+                animateTo(targetScene = fromScene, targetOffset = 0f)
+            }
+        }
+    }
 
     /**
-     * Whether the offset is animated (the user lifted their finger) or if it is driven by gesture.
+     * Whether the swipe to the target scene should be committed or not. This is inspired by
+     * SwipeableV2.computeTarget().
      */
-    var isAnimatingOffset by mutableStateOf(false)
-
-    /** The animatable used to animate the offset once the user lifted its finger. */
-    val offsetAnimatable = Animatable(0f, visibilityThreshold = OffsetVisibilityThreshold)
-
-    /** Job to check that there is at most one offset animation in progress. */
-    private var offsetAnimationJob: Job? = null
-
-    /** Ends any previous [offsetAnimationJob] and runs the new [job]. */
-    fun startOffsetAnimation(job: () -> Job) {
-        stopOffsetAnimation()
-        offsetAnimationJob = job()
-    }
-
-    /** Stops any ongoing offset animation. */
-    fun stopOffsetAnimation() {
-        offsetAnimationJob?.cancel()
-    }
-
-    /** The absolute distance between [fromScene] and [toScene]. */
-    var absoluteDistance = 0f
-
-    /**
-     * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is above
-     * or to the left of [toScene].
-     */
-    var _distance by mutableFloatStateOf(0f)
-    val distance: Float
-        get() = _distance
-}
-
-/** The destination scene when swiping up or left from [this@upOrLeft]. */
-private fun Scene.upOrLeft(orientation: Orientation): SceneKey? {
-    return when (orientation) {
-        Orientation.Vertical -> userActions[Swipe.Up]
-        Orientation.Horizontal -> userActions[Swipe.Left]
-    }
-}
-
-/** The destination scene when swiping down or right from [this@downOrRight]. */
-private fun Scene.downOrRight(orientation: Orientation): SceneKey? {
-    return when (orientation) {
-        Orientation.Vertical -> userActions[Swipe.Down]
-        Orientation.Horizontal -> userActions[Swipe.Right]
-    }
-}
-
-/** Whether swipe should be enabled in the given [orientation]. */
-private fun Scene.shouldEnableSwipes(orientation: Orientation): Boolean {
-    return upOrLeft(orientation) != null || downOrRight(orientation) != null
-}
-
-private fun Orientation.opposite(): Orientation {
-    return when (this) {
-        Orientation.Vertical -> Orientation.Horizontal
-        Orientation.Horizontal -> Orientation.Vertical
-    }
-}
-
-private fun onDragStarted(
-    layoutImpl: SceneTransitionLayoutImpl,
-    transition: SwipeTransition,
-    orientation: Orientation,
-) {
-    if (layoutImpl.state.transitionState == transition) {
-        // This [transition] was already driving the animation: simply take over it.
-        if (transition.isAnimatingOffset) {
-            // Stop animating and start from where the current offset. Setting the animation job to
-            // `null` will effectively cancel the animation.
-            transition.stopOffsetAnimation()
-            transition.dragOffset = transition.offsetAnimatable.value
+    private fun shouldCommitSwipe(
+        offset: Float,
+        distance: Float,
+        velocity: Float,
+        wasCommitted: Boolean,
+    ): Boolean {
+        fun isCloserToTarget(): Boolean {
+            return (offset - distance).absoluteValue < offset.absoluteValue
         }
 
-        return
-    }
-
-    // TODO(b/290184746): Better handle interruptions here if state != idle.
-
-    val fromScene = layoutImpl.scene(layoutImpl.state.transitionState.currentScene)
-
-    transition._currentScene = fromScene
-    transition._fromScene = fromScene
-
-    // We don't know where we are transitioning to yet given that the drag just started, so set it
-    // to fromScene, which will effectively be treated the same as Idle(fromScene).
-    transition._toScene = fromScene
-
-    transition.stopOffsetAnimation()
-    transition.dragOffset = 0f
-
-    // Use the layout size in the swipe orientation for swipe distance.
-    // TODO(b/290184746): Also handle custom distances for transitions. With smaller distances, we
-    // will also have to make sure that we correctly handle overscroll.
-    transition.absoluteDistance =
-        when (orientation) {
-            Orientation.Horizontal -> layoutImpl.size.width
-            Orientation.Vertical -> layoutImpl.size.height
-        }.toFloat()
-
-    if (transition.absoluteDistance > 0f) {
-        layoutImpl.state.transitionState = transition
-    }
-}
-
-private fun onDrag(
-    layoutImpl: SceneTransitionLayoutImpl,
-    transition: SwipeTransition,
-    orientation: Orientation,
-    delta: Float,
-) {
-    transition.dragOffset += delta
-
-    // First check transition.fromScene should be changed for the case where the user quickly swiped
-    // twice in a row to accelerate the transition and go from A => B then B => C really fast.
-    maybeHandleAcceleratedSwipe(transition, orientation)
-
-    val offset = transition.dragOffset
-    val fromScene = transition._fromScene
-
-    // Compute the target scene depending on the current offset.
-    val target = fromScene.findTargetSceneAndDistance(orientation, offset, layoutImpl)
-
-    if (transition._toScene.key != target.sceneKey) {
-        transition._toScene = layoutImpl.scenes.getValue(target.sceneKey)
-    }
-
-    if (transition._distance != target.distance) {
-        transition._distance = target.distance
-    }
-}
-
-/**
- * Change fromScene in the case where the user quickly swiped multiple times in the same direction
- * to accelerate the transition from A => B then B => C.
- */
-private fun maybeHandleAcceleratedSwipe(
-    transition: SwipeTransition,
-    orientation: Orientation,
-) {
-    val toScene = transition._toScene
-    val fromScene = transition._fromScene
-
-    // If the swipe was not committed, don't do anything.
-    if (fromScene == toScene || transition._currentScene != toScene) {
-        return
-    }
-
-    // If the offset is past the distance then let's change fromScene so that the user can swipe to
-    // the next screen or go back to the previous one.
-    val offset = transition.dragOffset
-    val absoluteDistance = transition.absoluteDistance
-    if (offset <= -absoluteDistance && fromScene.upOrLeft(orientation) == toScene.key) {
-        transition.dragOffset += absoluteDistance
-        transition._fromScene = toScene
-    } else if (offset >= absoluteDistance && fromScene.downOrRight(orientation) == toScene.key) {
-        transition.dragOffset -= absoluteDistance
-        transition._fromScene = toScene
-    }
-
-    // Important note: toScene and distance will be updated right after this function is called,
-    // using fromScene and dragOffset.
-}
-
-private data class TargetScene(
-    val sceneKey: SceneKey,
-    val distance: Float,
-)
-
-private fun Scene.findTargetSceneAndDistance(
-    orientation: Orientation,
-    directionOffset: Float,
-    layoutImpl: SceneTransitionLayoutImpl,
-): TargetScene {
-    val maxDistance =
-        when (orientation) {
-            Orientation.Horizontal -> layoutImpl.size.width
-            Orientation.Vertical -> layoutImpl.size.height
-        }.toFloat()
-
-    val upOrLeft = upOrLeft(orientation)
-    val downOrRight = downOrRight(orientation)
-
-    // Compute the target scene depending on the current offset.
-    return when {
-        directionOffset < 0f && upOrLeft != null -> {
-            TargetScene(
-                sceneKey = upOrLeft,
-                distance = -maxDistance,
-            )
+        // Swiping up or left.
+        if (distance < 0f) {
+            return if (offset > 0f || velocity >= velocityThreshold) {
+                false
+            } else {
+                velocity <= -velocityThreshold ||
+                    (offset <= -positionalThreshold && !wasCommitted) ||
+                    isCloserToTarget()
+            }
         }
-        directionOffset > 0f && downOrRight != null -> {
-            TargetScene(
-                sceneKey = downOrRight,
-                distance = maxDistance,
-            )
-        }
-        else -> {
-            TargetScene(
-                sceneKey = key,
-                distance = 0f,
-            )
-        }
-    }
-}
 
-private fun CoroutineScope.onDragStopped(
-    layoutImpl: SceneTransitionLayoutImpl,
-    transition: SwipeTransition,
-    velocity: Float,
-    velocityThreshold: Float,
-    positionalThreshold: Float,
-    canChangeScene: Boolean = true,
-) {
-    // The state was changed since the drag started; don't do anything.
-    if (layoutImpl.state.transitionState != transition) {
-        return
-    }
-
-    // We were not animating.
-    if (transition._fromScene == transition._toScene) {
-        layoutImpl.state.transitionState = TransitionState.Idle(transition._fromScene.key)
-        return
-    }
-
-    // Compute the destination scene (and therefore offset) to settle in.
-    val targetScene: Scene
-    val targetOffset: Float
-    val offset = transition.dragOffset
-    val distance = transition.distance
-    if (
-        canChangeScene &&
-            shouldCommitSwipe(
-                offset,
-                distance,
-                velocity,
-                velocityThreshold,
-                positionalThreshold,
-                wasCommitted = transition._currentScene == transition._toScene,
-            )
-    ) {
-        targetOffset = distance
-        targetScene = transition._toScene
-    } else {
-        targetOffset = 0f
-        targetScene = transition._fromScene
-    }
-
-    // If the effective current scene changed, it should be reflected right now in the current scene
-    // state, even before the settle animation is ongoing. That way all the swipeables and back
-    // handlers will be refreshed and the user can for instance quickly swipe vertically from A => B
-    // then horizontally from B => C, or swipe from A => B then immediately go back B => A.
-    if (targetScene != transition._currentScene) {
-        transition._currentScene = targetScene
-        layoutImpl.onChangeScene(targetScene.key)
-    }
-
-    animateOffset(
-        transition = transition,
-        layoutImpl = layoutImpl,
-        initialVelocity = velocity,
-        targetOffset = targetOffset,
-        targetScene = targetScene.key
-    )
-}
-
-/**
- * Whether the swipe to the target scene should be committed or not. This is inspired by
- * SwipeableV2.computeTarget().
- */
-private fun shouldCommitSwipe(
-    offset: Float,
-    distance: Float,
-    velocity: Float,
-    velocityThreshold: Float,
-    positionalThreshold: Float,
-    wasCommitted: Boolean,
-): Boolean {
-    fun isCloserToTarget(): Boolean {
-        return (offset - distance).absoluteValue < offset.absoluteValue
-    }
-
-    // Swiping up or left.
-    if (distance < 0f) {
-        return if (offset > 0f || velocity >= velocityThreshold) {
+        // Swiping down or right.
+        return if (offset < 0f || velocity <= -velocityThreshold) {
             false
         } else {
-            velocity <= -velocityThreshold ||
-                (offset <= -positionalThreshold && !wasCommitted) ||
+            velocity >= velocityThreshold ||
+                (offset >= positionalThreshold && !wasCommitted) ||
                 isCloserToTarget()
         }
     }
 
-    // Swiping down or right.
-    return if (offset < 0f || velocity <= -velocityThreshold) {
-        false
-    } else {
-        velocity >= velocityThreshold ||
-            (offset >= positionalThreshold && !wasCommitted) ||
-            isCloserToTarget()
-    }
-}
-
-private fun CoroutineScope.animateOffset(
-    transition: SwipeTransition,
-    layoutImpl: SceneTransitionLayoutImpl,
-    initialVelocity: Float,
-    targetOffset: Float,
-    targetScene: SceneKey,
-) {
-    transition.startOffsetAnimation {
-        launch {
-                if (!transition.isAnimatingOffset) {
-                    transition.offsetAnimatable.snapTo(transition.dragOffset)
+    private fun animateOffset(
+        initialVelocity: Float,
+        targetOffset: Float,
+        targetScene: SceneKey,
+    ) {
+        swipeTransition.startOffsetAnimation {
+            coroutineScope.launch {
+                if (!isAnimatingOffset) {
+                    swipeTransition.offsetAnimatable.snapTo(swipeTransition.dragOffset)
                 }
-                transition.isAnimatingOffset = true
+                isAnimatingOffset = true
 
-                transition.offsetAnimatable.animateTo(
+                swipeTransition.offsetAnimatable.animateTo(
                     targetOffset,
                     // TODO(b/290184746): Make this spring spec configurable.
                     spring(
@@ -471,64 +432,214 @@
                     initialVelocity = initialVelocity,
                 )
 
+                isAnimatingOffset = false
+
                 // Now that the animation is done, the state should be idle. Note that if the state
                 // was changed since this animation started, some external code changed it and we
                 // shouldn't do anything here. Note also that this job will be cancelled in the case
                 // where the user intercepts this swipe.
-                if (layoutImpl.state.transitionState == transition) {
-                    layoutImpl.state.transitionState = TransitionState.Idle(targetScene)
+                if (isDrivingTransition) {
+                    transitionState = TransitionState.Idle(targetScene)
                 }
             }
-            .also { it.invokeOnCompletion { transition.isAnimatingOffset = false } }
+        }
+    }
+
+    private class SwipeTransition(initialScene: Scene) : TransitionState.Transition {
+        var _currentScene by mutableStateOf(initialScene)
+        override val currentScene: SceneKey
+            get() = _currentScene.key
+
+        var _fromScene by mutableStateOf(initialScene)
+        override val fromScene: SceneKey
+            get() = _fromScene.key
+
+        var _toScene by mutableStateOf(initialScene)
+        override val toScene: SceneKey
+            get() = _toScene.key
+
+        override val progress: Float
+            get() {
+                val offset = if (isAnimatingOffset) offsetAnimatable.value else dragOffset
+                if (distance == 0f) {
+                    // This can happen only if fromScene == toScene.
+                    error(
+                        "Transition.progress should be called only when Transition.fromScene != " +
+                            "Transition.toScene"
+                    )
+                }
+                return offset / distance
+            }
+
+        override val isUserInputDriven = true
+
+        /** The current offset caused by the drag gesture. */
+        var dragOffset by mutableFloatStateOf(0f)
+
+        /**
+         * Whether the offset is animated (the user lifted their finger) or if it is driven by
+         * gesture.
+         */
+        var isAnimatingOffset by mutableStateOf(false)
+
+        /** The animatable used to animate the offset once the user lifted its finger. */
+        val offsetAnimatable = Animatable(0f, OffsetVisibilityThreshold)
+
+        /** Job to check that there is at most one offset animation in progress. */
+        private var offsetAnimationJob: Job? = null
+
+        /** Ends any previous [offsetAnimationJob] and runs the new [job]. */
+        fun startOffsetAnimation(job: () -> Job) {
+            stopOffsetAnimation()
+            offsetAnimationJob = job()
+        }
+
+        /** Stops any ongoing offset animation. */
+        fun stopOffsetAnimation() {
+            offsetAnimationJob?.cancel()
+
+            if (isAnimatingOffset) {
+                isAnimatingOffset = false
+                dragOffset = offsetAnimatable.value
+            }
+        }
+
+        /** The absolute distance between [fromScene] and [toScene]. */
+        var absoluteDistance = 0f
+
+        /**
+         * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is
+         * above or to the left of [toScene].
+         */
+        var _distance by mutableFloatStateOf(0f)
+        val distance: Float
+            get() = _distance
+    }
+
+    companion object {
+        private const val TAG = "SceneGestureHandler"
     }
 }
 
-private fun CoroutineScope.animateOverscroll(
-    layoutImpl: SceneTransitionLayoutImpl,
-    transition: SwipeTransition,
-    velocity: Velocity,
-    orientation: Orientation,
-): Velocity {
-    val velocityAmount =
-        when (orientation) {
-            Orientation.Vertical -> velocity.y
-            Orientation.Horizontal -> velocity.x
+private class SceneDraggableHandler(
+    private val gestureHandler: SceneGestureHandler,
+) : DraggableHandler {
+    override suspend fun onDragStarted(coroutineScope: CoroutineScope, startedPosition: Offset) {
+        gestureHandler.onDragStarted()
+    }
+
+    override fun onDelta(pixels: Float) {
+        gestureHandler.onDrag(delta = pixels)
+    }
+
+    override suspend fun onDragStopped(coroutineScope: CoroutineScope, velocity: Float) {
+        gestureHandler.onDragStopped(velocity = velocity, canChangeScene = true)
+    }
+}
+
+@VisibleForTesting
+class SceneNestedScrollHandler(
+    private val gestureHandler: SceneGestureHandler,
+) : NestedScrollHandler {
+    override val connection: PriorityNestedScrollConnection = nestedScrollConnection()
+
+    private fun Offset.toAmount() =
+        when (gestureHandler.orientation) {
+            Orientation.Horizontal -> x
+            Orientation.Vertical -> y
         }
 
-    if (velocityAmount == 0f) {
-        // There is no remaining velocity
-        return Velocity.Zero
+    private fun Velocity.toAmount() =
+        when (gestureHandler.orientation) {
+            Orientation.Horizontal -> x
+            Orientation.Vertical -> y
+        }
+
+    private fun Float.toOffset() =
+        when (gestureHandler.orientation) {
+            Orientation.Horizontal -> Offset(x = this, y = 0f)
+            Orientation.Vertical -> Offset(x = 0f, y = this)
+        }
+
+    private fun nestedScrollConnection(): PriorityNestedScrollConnection {
+        // The next potential scene is calculated during the canStart
+        var nextScene: SceneKey? = null
+
+        // This is the scene on which we will have priority during the scroll gesture.
+        var priorityScene: SceneKey? = null
+
+        // If we performed a long gesture before entering priority mode, we would have to avoid
+        // moving on to the next scene.
+        var gestureStartedOnNestedChild = false
+
+        fun findNextScene(amount: Float): SceneKey? {
+            val fromScene = gestureHandler.currentScene
+            return when {
+                amount < 0f -> fromScene.upOrLeft(gestureHandler.orientation)
+                amount > 0f -> fromScene.downOrRight(gestureHandler.orientation)
+                else -> null
+            }
+        }
+
+        return PriorityNestedScrollConnection(
+            canStartPreScroll = { offsetAvailable, offsetBeforeStart ->
+                gestureStartedOnNestedChild = offsetBeforeStart != Offset.Zero
+
+                val canInterceptPreScroll =
+                    gestureHandler.isDrivingTransition &&
+                        !gestureStartedOnNestedChild &&
+                        offsetAvailable.toAmount() != 0f
+
+                if (!canInterceptPreScroll) return@PriorityNestedScrollConnection false
+
+                nextScene = gestureHandler.swipeTransitionToScene.key
+
+                true
+            },
+            canStartPostScroll = { offsetAvailable, offsetBeforeStart ->
+                val amount = offsetAvailable.toAmount()
+                if (amount == 0f) return@PriorityNestedScrollConnection false
+
+                gestureStartedOnNestedChild = offsetBeforeStart != Offset.Zero
+                nextScene = findNextScene(amount)
+                nextScene != null
+            },
+            canStartPostFling = { velocityAvailable ->
+                val amount = velocityAvailable.toAmount()
+                if (amount == 0f) return@PriorityNestedScrollConnection false
+
+                // We could start an overscroll animation
+                gestureStartedOnNestedChild = true
+                nextScene = findNextScene(amount)
+                nextScene != null
+            },
+            canContinueScroll = { priorityScene == gestureHandler.swipeTransitionToScene.key },
+            onStart = {
+                priorityScene = nextScene
+                gestureHandler.onDragStarted()
+            },
+            onScroll = { offsetAvailable ->
+                val amount = offsetAvailable.toAmount()
+
+                // TODO(b/297842071) We should handle the overscroll or slow drag if the gesture is
+                // initiated in a nested child.
+                gestureHandler.onDrag(amount)
+
+                amount.toOffset()
+            },
+            onStop = { velocityAvailable ->
+                priorityScene = null
+
+                gestureHandler.onDragStopped(
+                    velocity = velocityAvailable.toAmount(),
+                    canChangeScene = !gestureStartedOnNestedChild
+                )
+
+                // The onDragStopped animation consumes any remaining velocity.
+                velocityAvailable
+            },
+        )
     }
-
-    val fromScene = layoutImpl.scene(layoutImpl.state.transitionState.currentScene)
-    val target = fromScene.findTargetSceneAndDistance(orientation, velocityAmount, layoutImpl)
-    val isValidTarget = target.distance != 0f && target.sceneKey != fromScene.key
-
-    if (!isValidTarget || layoutImpl.state.transitionState == transition) {
-        // We have not found a valid target or we are already in a transition
-        return Velocity.Zero
-    }
-
-    transition._currentScene = fromScene
-    transition._fromScene = fromScene
-    transition._toScene = layoutImpl.scene(target.sceneKey)
-    transition._distance = target.distance
-    transition.absoluteDistance = target.distance.absoluteValue
-    transition.stopOffsetAnimation()
-    transition.dragOffset = 0f
-
-    layoutImpl.state.transitionState = transition
-
-    animateOffset(
-        transition = transition,
-        layoutImpl = layoutImpl,
-        initialVelocity = velocityAmount,
-        targetOffset = 0f,
-        targetScene = fromScene.key
-    )
-
-    // The animateOffset animation consumes any remaining velocity.
-    return velocity
 }
 
 /**
@@ -536,127 +647,3 @@
  * which the animation can stop.
  */
 private const val OffsetVisibilityThreshold = 0.5f
-
-@Composable
-private fun rememberSwipeToSceneNestedScrollConnection(
-    orientation: Orientation,
-    coroutineScope: CoroutineScope,
-    draggableState: DraggableState,
-    transition: SwipeTransition,
-    layoutImpl: SceneTransitionLayoutImpl,
-    velocityThreshold: Float,
-    positionalThreshold: Float,
-): PriorityPostNestedScrollConnection {
-    val density = LocalDensity.current
-    val scrollConnection =
-        remember(
-            orientation,
-            coroutineScope,
-            draggableState,
-            transition,
-            layoutImpl,
-            velocityThreshold,
-            positionalThreshold,
-            density,
-        ) {
-            fun Offset.toAmount() =
-                when (orientation) {
-                    Orientation.Horizontal -> x
-                    Orientation.Vertical -> y
-                }
-
-            fun Velocity.toAmount() =
-                when (orientation) {
-                    Orientation.Horizontal -> x
-                    Orientation.Vertical -> y
-                }
-
-            fun Float.toOffset() =
-                when (orientation) {
-                    Orientation.Horizontal -> Offset(x = this, y = 0f)
-                    Orientation.Vertical -> Offset(x = 0f, y = this)
-                }
-
-            // The next potential scene is calculated during the canStart
-            var nextScene: SceneKey? = null
-
-            // This is the scene on which we will have priority during the scroll gesture.
-            var priorityScene: SceneKey? = null
-
-            // If we performed a long gesture before entering priority mode, we would have to avoid
-            // moving on to the next scene.
-            var gestureStartedOnNestedChild = false
-
-            PriorityPostNestedScrollConnection(
-                canStart = { offsetAvailable, offsetBeforeStart ->
-                    val amount = offsetAvailable.toAmount()
-                    if (amount == 0f) return@PriorityPostNestedScrollConnection false
-
-                    gestureStartedOnNestedChild = offsetBeforeStart != Offset.Zero
-
-                    val fromScene = layoutImpl.scene(layoutImpl.state.transitionState.currentScene)
-                    nextScene =
-                        when {
-                            amount < 0f -> fromScene.upOrLeft(orientation)
-                            amount > 0f -> fromScene.downOrRight(orientation)
-                            else -> null
-                        }
-
-                    nextScene != null
-                },
-                canContinueScroll = { priorityScene == transition._toScene.key },
-                onStart = {
-                    priorityScene = nextScene
-                    onDragStarted(layoutImpl, transition, orientation)
-                },
-                onScroll = { offsetAvailable ->
-                    val amount = offsetAvailable.toAmount()
-
-                    // TODO(b/297842071) We should handle the overscroll or slow drag if the gesture
-                    // is initiated in a nested child.
-
-                    // Appends a new coroutine to attempt to drag by [amount] px. In this case we
-                    // are assuming that the [coroutineScope] is tied to the main thread and that
-                    // calls to [launch] are therefore queued.
-                    coroutineScope.launch { draggableState.drag { dragBy(amount) } }
-
-                    amount.toOffset()
-                },
-                onStop = { velocityAvailable ->
-                    priorityScene = null
-
-                    coroutineScope.onDragStopped(
-                        layoutImpl = layoutImpl,
-                        transition = transition,
-                        velocity = velocityAvailable.toAmount(),
-                        velocityThreshold = velocityThreshold,
-                        positionalThreshold = positionalThreshold,
-                        canChangeScene = !gestureStartedOnNestedChild
-                    )
-
-                    // The onDragStopped animation consumes any remaining velocity.
-                    velocityAvailable
-                },
-                onPostFling = { velocityAvailable ->
-                    // If there is any velocity left, we can try running an overscroll animation
-                    // between scenes.
-                    coroutineScope.animateOverscroll(
-                        layoutImpl = layoutImpl,
-                        transition = transition,
-                        velocity = velocityAvailable,
-                        orientation = orientation
-                    )
-                },
-            )
-        }
-    DisposableEffect(scrollConnection) {
-        onDispose {
-            coroutineScope.launch {
-                // This should ensure that the draggableState is in a consistent state and that it
-                // does not cause any unexpected behavior.
-                scrollConnection.reset()
-            }
-        }
-    }
-    return scrollConnection
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
similarity index 74%
rename from packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnection.kt
rename to packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
index 793a9a5..824c10b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
@@ -22,22 +22,23 @@
 import androidx.compose.ui.unit.Velocity
 
 /**
- * This [NestedScrollConnection] waits for a child to scroll ([onPostScroll]), and then decides (via
- * [canStart]) if it should take over scrolling. If it does, it will scroll before its children,
- * until [canContinueScroll] allows it.
+ * This [NestedScrollConnection] waits for a child to scroll ([onPreScroll] or [onPostScroll]), and
+ * then decides (via [canStartPreScroll] or [canStartPostScroll]) if it should take over scrolling.
+ * If it does, it will scroll before its children, until [canContinueScroll] allows it.
  *
  * Note: Call [reset] before destroying this object to make sure you always get a call to [onStop]
  * after [onStart].
  *
  * @sample com.android.compose.animation.scene.rememberSwipeToSceneNestedScrollConnection
  */
-class PriorityPostNestedScrollConnection(
-    private val canStart: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
+class PriorityNestedScrollConnection(
+    private val canStartPreScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
+    private val canStartPostScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
+    private val canStartPostFling: (velocityAvailable: Velocity) -> Boolean,
     private val canContinueScroll: () -> Boolean,
     private val onStart: () -> Unit,
     private val onScroll: (offsetAvailable: Offset) -> Offset,
     private val onStop: (velocityAvailable: Velocity) -> Velocity,
-    private val onPostFling: suspend (velocityAvailable: Velocity) -> Velocity,
 ) : NestedScrollConnection {
 
     /** In priority mode [onPreScroll] events are first consumed by the parent, via [onScroll]. */
@@ -57,26 +58,21 @@
         if (
             isPriorityMode ||
                 source == NestedScrollSource.Fling ||
-                !canStart(available, offsetBeforeStart)
+                !canStartPostScroll(available, offsetBeforeStart)
         ) {
             // The priority mode cannot start so we won't consume the available offset.
             return Offset.Zero
         }
 
-        // Step 1: It's our turn! We start capturing scroll events when one of our children has an
-        // available offset following a scroll event.
-        isPriorityMode = true
-
-        // Note: onStop will be called if we cannot continue to scroll (step 3a), or the finger is
-        // lifted (step 3b), or this object has been destroyed (step 3c).
-        onStart()
-
-        return onScroll(available)
+        return onPriorityStart(available)
     }
 
     override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
         if (!isPriorityMode) {
             if (source != NestedScrollSource.Fling) {
+                if (canStartPreScroll(available, offsetScrolledBeforePriorityMode)) {
+                    return onPriorityStart(available)
+                }
                 // We want to track the amount of offset consumed before entering priority mode
                 offsetScrolledBeforePriorityMode += available
             }
@@ -87,6 +83,11 @@
         if (!canContinueScroll()) {
             // Step 3a: We have lost priority and we no longer need to intercept scroll events.
             onPriorityStop(velocity = Velocity.Zero)
+
+            // We've just reset offsetScrolledBeforePriorityMode to Offset.Zero
+            // We want to track the amount of offset consumed before entering priority mode
+            offsetScrolledBeforePriorityMode += available
+
             return Offset.Zero
         }
 
@@ -101,7 +102,14 @@
     }
 
     override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
-        return onPostFling(available)
+        if (!canStartPostFling(available)) {
+            return Velocity.Zero
+        }
+
+        onPriorityStart(available = Offset.Zero)
+
+        // This is the last event of a scroll gesture.
+        return onPriorityStop(available)
     }
 
     /** Method to call before destroying the object or to reset the initial state. */
@@ -110,8 +118,23 @@
         onPriorityStop(velocity = Velocity.Zero)
     }
 
-    private fun onPriorityStop(velocity: Velocity): Velocity {
+    private fun onPriorityStart(available: Offset): Offset {
+        if (isPriorityMode) {
+            error("This should never happen, onPriorityStart() was called when isPriorityMode")
+        }
 
+        // Step 1: It's our turn! We start capturing scroll events when one of our children has an
+        // available offset following a scroll event.
+        isPriorityMode = true
+
+        // Note: onStop will be called if we cannot continue to scroll (step 3a), or the finger is
+        // lifted (step 3b), or this object has been destroyed (step 3c).
+        onStart()
+
+        return onScroll(available)
+    }
+
+    private fun onPriorityStop(velocity: Velocity): Velocity {
         // We can restart tracking the consumed offsets from scratch.
         offsetScrolledBeforePriorityMode = Offset.Zero
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
new file mode 100644
index 0000000..9b9e70d
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
@@ -0,0 +1,315 @@
+package com.android.compose.animation.scene
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.material3.Text
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.Velocity
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.TestScenes.SceneC
+import com.android.compose.animation.scene.TransitionState.Idle
+import com.android.compose.animation.scene.TransitionState.Transition
+import com.android.compose.test.MonotonicClockTestScope
+import com.android.compose.test.runMonotonicClockTest
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val SCREEN_SIZE = 100f
+
+@RunWith(AndroidJUnit4::class)
+class SceneGestureHandlerTest {
+    private class TestGestureScope(
+        val coroutineScope: MonotonicClockTestScope,
+    ) {
+        private var internalCurrentScene: SceneKey by mutableStateOf(SceneA)
+
+        private val layoutState: SceneTransitionLayoutState =
+            SceneTransitionLayoutState(internalCurrentScene)
+
+        private val scenesBuilder: SceneTransitionLayoutScope.() -> Unit = {
+            scene(
+                key = SceneA,
+                userActions = mapOf(Swipe.Up to SceneB, Swipe.Down to SceneC),
+            ) {
+                Text("SceneA")
+            }
+            scene(SceneB) { Text("SceneB") }
+            scene(SceneC) { Text("SceneC") }
+        }
+
+        val sceneGestureHandler =
+            SceneGestureHandler(
+                layoutImpl =
+                    SceneTransitionLayoutImpl(
+                            onChangeScene = { internalCurrentScene = it },
+                            builder = scenesBuilder,
+                            transitions = EmptyTestTransitions,
+                            state = layoutState,
+                            density = Density(1f)
+                        )
+                        .also { it.size = IntSize(SCREEN_SIZE.toInt(), SCREEN_SIZE.toInt()) },
+                orientation = Orientation.Vertical,
+                coroutineScope = coroutineScope,
+            )
+
+        val draggable = sceneGestureHandler.draggable
+
+        val nestedScroll = sceneGestureHandler.nestedScroll.connection
+
+        val velocityThreshold = sceneGestureHandler.velocityThreshold
+
+        // 10% of the screen
+        val deltaInPixels10 = SCREEN_SIZE * 0.1f
+
+        // Offset y: 10% of the screen
+        val offsetY10 = Offset(x = 0f, y = deltaInPixels10)
+
+        val transitionState: TransitionState
+            get() = layoutState.transitionState
+
+        fun advanceUntilIdle() {
+            coroutineScope.testScheduler.advanceUntilIdle()
+        }
+
+        fun runCurrent() {
+            coroutineScope.testScheduler.runCurrent()
+        }
+
+        fun assertScene(currentScene: SceneKey, isIdle: Boolean) {
+            val idleMsg = if (isIdle) "MUST" else "MUST NOT"
+            assertWithMessage("transitionState $idleMsg be Idle")
+                .that(transitionState is Idle)
+                .isEqualTo(isIdle)
+            assertThat(transitionState.currentScene).isEqualTo(currentScene)
+        }
+    }
+
+    @OptIn(ExperimentalTestApi::class)
+    private fun runGestureTest(block: suspend TestGestureScope.() -> Unit) {
+        runMonotonicClockTest { TestGestureScope(coroutineScope = this).block() }
+    }
+
+    @Test
+    fun testPreconditions() = runGestureTest { assertScene(currentScene = SceneA, isIdle = true) }
+
+    @Test
+    fun onDragStarted_shouldStartATransition() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+    }
+
+    @Test
+    fun afterSceneTransitionIsStarted_interceptDragEvents() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+        val transition = transitionState as Transition
+
+        draggable.onDelta(pixels = deltaInPixels10)
+        assertThat(transition.progress).isEqualTo(0.1f)
+
+        draggable.onDelta(pixels = deltaInPixels10)
+        assertThat(transition.progress).isEqualTo(0.2f)
+    }
+
+    @Test
+    fun onDragStoppedAfterDrag_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDelta(pixels = deltaInPixels10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDragStopped(
+            coroutineScope = coroutineScope,
+            velocity = velocityThreshold - 0.01f,
+        )
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertScene(currentScene = SceneA, isIdle = true)
+    }
+
+    @Test
+    fun onDragStoppedAfterDrag_velocityAtLeastThreshold_goToNextScene() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDelta(pixels = deltaInPixels10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDragStopped(
+            coroutineScope = coroutineScope,
+            velocity = velocityThreshold,
+        )
+        assertScene(currentScene = SceneC, isIdle = false)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertScene(currentScene = SceneC, isIdle = true)
+    }
+
+    @Test
+    fun onDragStoppedAfterStarted_returnImmediatelyToIdle() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDragStopped(coroutineScope = coroutineScope, velocity = 0f)
+        assertScene(currentScene = SceneA, isIdle = true)
+    }
+
+    @Test
+    fun startGestureDuringAnimatingOffset_shouldImmediatelyStopTheAnimation() = runGestureTest {
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDelta(pixels = deltaInPixels10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        draggable.onDragStopped(
+            coroutineScope = coroutineScope,
+            velocity = velocityThreshold,
+        )
+
+        // The stop animation is not started yet
+        assertThat(sceneGestureHandler.isAnimatingOffset).isFalse()
+
+        runCurrent()
+
+        assertThat(sceneGestureHandler.isAnimatingOffset).isTrue()
+        assertThat(sceneGestureHandler.isDrivingTransition).isTrue()
+        assertScene(currentScene = SceneC, isIdle = false)
+
+        // Start a new gesture while the offset is animating
+        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        assertThat(sceneGestureHandler.isAnimatingOffset).isFalse()
+    }
+
+    @Test
+    fun onInitialPreScroll_doNotChangeState() = runGestureTest {
+        nestedScroll.onPreScroll(available = offsetY10, source = NestedScrollSource.Drag)
+        assertScene(currentScene = SceneA, isIdle = true)
+    }
+
+    @Test
+    fun onPostScrollWithNothingAvailable_doNotChangeState() = runGestureTest {
+        val consumed =
+            nestedScroll.onPostScroll(
+                consumed = Offset.Zero,
+                available = Offset.Zero,
+                source = NestedScrollSource.Drag
+            )
+
+        assertScene(currentScene = SceneA, isIdle = true)
+        assertThat(consumed).isEqualTo(Offset.Zero)
+    }
+
+    @Test
+    fun onPostScrollWithSomethingAvailable_startSceneTransition() = runGestureTest {
+        val consumed =
+            nestedScroll.onPostScroll(
+                consumed = Offset.Zero,
+                available = offsetY10,
+                source = NestedScrollSource.Drag
+            )
+
+        assertScene(currentScene = SceneA, isIdle = false)
+        val transition = transitionState as Transition
+        assertThat(transition.progress).isEqualTo(0.1f)
+        assertThat(consumed).isEqualTo(offsetY10)
+    }
+
+    private fun TestGestureScope.nestedScrollEvents(
+        available: Offset,
+        consumedByScroll: Offset = Offset.Zero,
+    ) {
+        val consumedByPreScroll =
+            nestedScroll.onPreScroll(available = available, source = NestedScrollSource.Drag)
+        val consumed = consumedByPreScroll + consumedByScroll
+        nestedScroll.onPostScroll(
+            consumed = consumed,
+            available = available - consumed,
+            source = NestedScrollSource.Drag
+        )
+    }
+
+    @Test
+    fun afterSceneTransitionIsStarted_interceptPreScrollEvents() = runGestureTest {
+        nestedScrollEvents(available = offsetY10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        val transition = transitionState as Transition
+        assertThat(transition.progress).isEqualTo(0.1f)
+
+        // start intercept preScroll
+        val consumed =
+            nestedScroll.onPreScroll(available = offsetY10, source = NestedScrollSource.Drag)
+        assertThat(transition.progress).isEqualTo(0.2f)
+
+        // do nothing on postScroll
+        nestedScroll.onPostScroll(
+            consumed = consumed,
+            available = Offset.Zero,
+            source = NestedScrollSource.Drag
+        )
+        assertThat(transition.progress).isEqualTo(0.2f)
+
+        nestedScrollEvents(available = offsetY10)
+        assertThat(transition.progress).isEqualTo(0.3f)
+        assertScene(currentScene = SceneA, isIdle = false)
+    }
+
+    @Test
+    fun onPreFling_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
+        nestedScrollEvents(available = offsetY10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        nestedScroll.onPreFling(available = Velocity.Zero)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertScene(currentScene = SceneA, isIdle = true)
+    }
+
+    @Test
+    fun onPreFling_velocityAtLeastThreshold_goToNextScene() = runGestureTest {
+        nestedScrollEvents(available = offsetY10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        nestedScroll.onPreFling(available = Velocity(0f, velocityThreshold))
+        assertScene(currentScene = SceneC, isIdle = false)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertScene(currentScene = SceneC, isIdle = true)
+    }
+
+    @Test
+    fun scrollStartedInScene_doOverscrollAnimation() = runGestureTest {
+        // we started the scroll in the scene
+        nestedScrollEvents(available = offsetY10, consumedByScroll = offsetY10)
+
+        // now we can intercept the scroll events
+        nestedScrollEvents(available = offsetY10)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        nestedScroll.onPreFling(available = Velocity(0f, velocityThreshold))
+        // should start an overscroll animation (the gesture started in the scene)
+        assertScene(currentScene = SceneA, isIdle = false)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertScene(currentScene = SceneA, isIdle = true)
+    }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
similarity index 66%
rename from packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnectionTest.kt
rename to packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
index 8e2b77a..122774b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityPostNestedScrollConnectionTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
@@ -29,20 +29,22 @@
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
-class PriorityPostNestedScrollConnectionTest {
-    private var canStart = false
+class PriorityNestedScrollConnectionTest {
+    private var canStartPreScroll = false
+    private var canStartPostScroll = false
+    private var canStartPostFling = false
     private var canContinueScroll = false
     private var isStarted = false
     private var lastScroll: Offset? = null
     private var returnOnScroll = Offset.Zero
     private var lastStop: Velocity? = null
     private var returnOnStop = Velocity.Zero
-    private var lastOnPostFling: Velocity? = null
-    private var returnOnPostFling = Velocity.Zero
 
     private val scrollConnection =
-        PriorityPostNestedScrollConnection(
-            canStart = { _, _ -> canStart },
+        PriorityNestedScrollConnection(
+            canStartPreScroll = { _, _ -> canStartPreScroll },
+            canStartPostScroll = { _, _ -> canStartPostScroll },
+            canStartPostFling = { canStartPostFling },
             canContinueScroll = { canContinueScroll },
             onStart = { isStarted = true },
             onScroll = {
@@ -53,10 +55,6 @@
                 lastStop = it
                 returnOnStop
             },
-            onPostFling = {
-                lastOnPostFling = it
-                returnOnPostFling
-            },
         )
 
     private val offset1 = Offset(1f, 1f)
@@ -64,8 +62,29 @@
     private val velocity1 = Velocity(1f, 1f)
     private val velocity2 = Velocity(2f, 2f)
 
-    private fun startPriorityMode() {
-        canStart = true
+    @Test
+    fun step1_priorityModeShouldStartOnlyOnPreScroll() = runTest {
+        canStartPreScroll = true
+
+        scrollConnection.onPostScroll(
+            consumed = Offset.Zero,
+            available = Offset.Zero,
+            source = NestedScrollSource.Drag
+        )
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPreFling(available = Velocity.Zero)
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero)
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        assertThat(isStarted).isEqualTo(true)
+    }
+
+    private fun startPriorityModePostScroll() {
+        canStartPostScroll = true
         scrollConnection.onPostScroll(
             consumed = Offset.Zero,
             available = Offset.Zero,
@@ -75,7 +94,7 @@
 
     @Test
     fun step1_priorityModeShouldStartOnlyOnPostScroll() = runTest {
-        canStart = true
+        canStartPostScroll = true
 
         scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
         assertThat(isStarted).isEqualTo(false)
@@ -86,7 +105,7 @@
         scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero)
         assertThat(isStarted).isEqualTo(false)
 
-        startPriorityMode()
+        startPriorityModePostScroll()
         assertThat(isStarted).isEqualTo(true)
     }
 
@@ -99,13 +118,13 @@
         )
         assertThat(isStarted).isEqualTo(false)
 
-        startPriorityMode()
+        startPriorityModePostScroll()
         assertThat(isStarted).isEqualTo(true)
     }
 
     @Test
     fun step1_onPriorityModeStarted_receiveAvailableOffset() {
-        canStart = true
+        canStartPostScroll = true
 
         scrollConnection.onPostScroll(
             consumed = offset1,
@@ -118,7 +137,7 @@
 
     @Test
     fun step2_onPriorityMode_shouldContinueIfAllowed() {
-        startPriorityMode()
+        startPriorityModePostScroll()
         canContinueScroll = true
 
         scrollConnection.onPreScroll(available = offset1, source = NestedScrollSource.Drag)
@@ -132,7 +151,7 @@
 
     @Test
     fun step3a_onPriorityMode_shouldStopIfCannotContinue() {
-        startPriorityMode()
+        startPriorityModePostScroll()
         canContinueScroll = false
 
         scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
@@ -142,7 +161,7 @@
 
     @Test
     fun step3b_onPriorityMode_shouldStopOnFling() = runTest {
-        startPriorityMode()
+        startPriorityModePostScroll()
         canContinueScroll = true
 
         scrollConnection.onPreFling(available = Velocity.Zero)
@@ -152,7 +171,7 @@
 
     @Test
     fun step3c_onPriorityMode_shouldStopOnReset() {
-        startPriorityMode()
+        startPriorityModePostScroll()
         canContinueScroll = true
 
         scrollConnection.reset()
@@ -162,11 +181,34 @@
 
     @Test
     fun receive_onPostFling() = runTest {
+        canStartPostFling = true
+
         scrollConnection.onPostFling(
             consumed = velocity1,
             available = velocity2,
         )
 
-        assertThat(lastOnPostFling).isEqualTo(velocity2)
+        assertThat(lastStop).isEqualTo(velocity2)
+    }
+
+    @Test
+    fun step1_priorityModeShouldStartOnlyOnPostFling() = runTest {
+        canStartPostFling = true
+
+        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPostScroll(
+            consumed = Offset.Zero,
+            available = Offset.Zero,
+            source = NestedScrollSource.Drag
+        )
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPreFling(available = Velocity.Zero)
+        assertThat(isStarted).isEqualTo(false)
+
+        scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero)
+        assertThat(isStarted).isEqualTo(true)
     }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/RunMonotonicClockTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/RunMonotonicClockTest.kt
new file mode 100644
index 0000000..cb122dc
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/RunMonotonicClockTest.kt
@@ -0,0 +1,27 @@
+package com.android.compose.test
+
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.TestMonotonicFrameClock
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.test.TestCoroutineScheduler
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.withContext
+
+/**
+ * This method creates a [CoroutineScope] that can be used in animations created in a composable
+ * function.
+ *
+ * The [TestCoroutineScheduler] is passed to provide the functionality to wait for idle.
+ */
+@ExperimentalTestApi
+fun runMonotonicClockTest(block: suspend MonotonicClockTestScope.() -> Unit) = runTest {
+    // We need a CoroutineScope (like a TestScope) to create a TestMonotonicFrameClock.
+    withContext(TestMonotonicFrameClock(this)) {
+        MonotonicClockTestScope(coroutineScope = this, testScheduler = testScheduler).block()
+    }
+}
+
+class MonotonicClockTestScope(
+    coroutineScope: CoroutineScope,
+    val testScheduler: TestCoroutineScheduler
+) : CoroutineScope by coroutineScope
diff --git a/packages/SystemUI/flag_check.py b/packages/SystemUI/flag_check.py
new file mode 100755
index 0000000..5db27d8
--- /dev/null
+++ b/packages/SystemUI/flag_check.py
@@ -0,0 +1,134 @@
+#! /usr/bin/env python3
+
+import sys
+import re
+import argparse
+
+# partially copied from tools/repohooks/rh/hooks.py
+
+TEST_MSG = """Commit message is missing a "Flag:" line.  It must match one of the
+following case-sensitive regex:
+
+    %s
+
+The Flag: stanza is regex matched and should describe whether your change is behind a flag or flags.
+
+As a CL author, you'll have a consistent place to describe the risk of the proposed change by explicitly calling out the name of the
+flag in addition to its state (ENABLED|DISABLED|DEVELOPMENT|TEAMFOOD|TRUNKFOOD|NEXTFOOD).
+
+Some examples below:
+
+Flag: NONE
+Flag: NA
+Flag: LEGACY ENABLE_ONE_SEARCH DISABLED
+Flag: ACONFIG com.android.launcher3.enable_twoline_allapps DEVELOPMENT
+Flag: ACONFIG com.android.launcher3.enable_twoline_allapps TRUNKFOOD
+
+Check the git history for more examples. It's a regex matched field.
+"""
+
+def main():
+    """Check the commit message for a 'Flag:' line."""
+    parser = argparse.ArgumentParser(
+        description='Check the commit message for a Flag: line.')
+    parser.add_argument('--msg',
+                        metavar='msg',
+                        type=str,
+                        nargs='?',
+                        default='HEAD',
+                        help='commit message to process.')
+    parser.add_argument(
+        '--files',
+        metavar='files',
+        nargs='?',
+        default='',
+        help=
+        'PREUPLOAD_FILES in repo upload to determine whether the check should run for the files.')
+    parser.add_argument(
+        '--project',
+        metavar='project',
+        type=str,
+        nargs='?',
+        default='',
+        help=
+        'REPO_PATH in repo upload to determine whether the check should run for this project.')
+
+    # Parse the arguments
+    args = parser.parse_args()
+    desc = args.msg
+    files = args.files
+    project = args.project
+
+    if not should_run_path(project, files):
+        return
+
+    field = 'Flag'
+    none = '(NONE|NA|N\/A)' # NONE|NA|N/A
+
+    typeExpression = '\s*(LEGACY|ACONFIG)' # [type:LEGACY|ACONFIG]
+
+    # legacyFlagName contains only uppercase alphabets with '_' - Ex: ENABLE_ONE_SEARCH
+    # Aconfig Flag name format = "packageName"."flagName"
+    # package name - Contains only lowercase alphabets + digits + '.' - Ex: com.android.launcher3
+    # For now alphabets, digits, "_", "." characters are allowed in flag name and not adding stricter format check.
+    #common_typos_disable
+    flagName = '([a-zA-z0-9_.])+'
+
+    #[state:ENABLED|DISABLED|DEVELOPMENT|TEAM*(TEAMFOOD)|TRUNK*(TRUNK_STAGING, TRUNK_FOOD)|NEXT*(NEXTFOOD)]
+    stateExpression = '\s*(ENABLED|DISABLED|DEVELOPMENT|TEAM[a-zA-z]*|TRUNK[a-zA-z]*|NEXT[a-zA-z]*)'
+    #common_typos_enable
+
+    readableRegexMsg = '\n\tFlag: (NONE|NA)\n\tFlag: LEGACY|ACONFIG FlagName|packageName.flagName ENABLED|DISABLED|DEVELOPMENT|TEAMFOOD|TRUNKFOOD|NEXTFOOD'
+
+    flagRegex = fr'^{field}: .*$'
+    check_flag = re.compile(flagRegex) #Flag:
+
+    # Ignore case for flag name format.
+    flagNameRegex = fr'(?i)^{field}:\s*({none}|{typeExpression}\s*{flagName}\s*{stateExpression})\s*'
+    check_flagName = re.compile(flagNameRegex) #Flag: <flag name format>
+
+    flagError = False
+    foundFlag = []
+    # Check for multiple "Flag:" lines and all lines should match this format
+    for line in desc.splitlines():
+        if check_flag.match(line):
+            if not check_flagName.match(line):
+                flagError = True
+                break
+            foundFlag.append(line)
+
+    # Throw error if
+    # 1. No "Flag:" line is found
+    # 2. "Flag:" doesn't follow right format.
+    if (not foundFlag) or (flagError):
+        error = TEST_MSG % (readableRegexMsg)
+        print(error)
+        sys.exit(1)
+
+    sys.exit(0)
+
+
+def should_run_path(path, files):
+    """Returns a boolean if this check should run with these paths.
+    If you want to check for a particular subdirectory under the path,
+    add a check here, call should_run_files and check for a specific sub dir path in should_run_files.
+    """
+    if not path:
+        return False
+    if path == 'frameworks/base':
+        return should_run_files(files)
+    # Default case, run for all other paths which calls this script.
+    return True
+
+
+def should_run_files(files):
+    """Returns a boolean if this check should run with these files."""
+    if not files:
+        return False
+    if 'packages/SystemUI' in files:
+        return True
+    return False
+
+
+if __name__ == '__main__':
+    main()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
diff --git a/packages/SystemUI/multivalentTestsForDevice b/packages/SystemUI/multivalentTestsForDevice
new file mode 120000
index 0000000..20ee34a
--- /dev/null
+++ b/packages/SystemUI/multivalentTestsForDevice
@@ -0,0 +1 @@
+multivalentTests
\ No newline at end of file
diff --git a/packages/SystemUI/multivalentTestsForDeviceless b/packages/SystemUI/multivalentTestsForDeviceless
new file mode 120000
index 0000000..20ee34a
--- /dev/null
+++ b/packages/SystemUI/multivalentTestsForDeviceless
@@ -0,0 +1 @@
+multivalentTests
\ No newline at end of file
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java
index a9d2ee3..403c7c5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java
@@ -19,7 +19,6 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.view.View;
-import android.widget.ImageView;
 
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.plugins.annotations.DependsOn;
@@ -51,21 +50,11 @@
     void addDarkReceiver(DarkReceiver receiver);
 
     /**
-     * Adds a receiver to receive callbacks onDarkChanged
-     */
-    void addDarkReceiver(ImageView imageView);
-
-    /**
      * Must have been previously been added through one of the addDarkReceive methods above.
      */
     void removeDarkReceiver(DarkReceiver object);
 
     /**
-     * Must have been previously been added through one of the addDarkReceive methods above.
-     */
-    void removeDarkReceiver(ImageView object);
-
-    /**
      * Used to reapply darkness on an object, must have previously been added through
      * addDarkReceiver.
       */
@@ -104,8 +93,8 @@
     }
 
     /**
-     * @return true if more than half of the view area are in any of the given
-     *         areas, false otherwise
+     * @return true if more than half of the view's area is in any of the given area Rects, false
+     *         otherwise
      */
     static boolean isInAreas(Collection<Rect> areas, View view) {
         if (areas.isEmpty()) {
@@ -120,9 +109,40 @@
     }
 
     /**
-     * @return true if more than half of the view area are in area, false
+     * @return true if more than half of the viewBounds are in any of the given area Rects, false
      *         otherwise
      */
+    static boolean isInAreas(Collection<Rect> areas, Rect viewBounds) {
+        if (areas.isEmpty()) {
+            return true;
+        }
+        for (Rect area : areas) {
+            if (isInArea(area, viewBounds)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** @return true if more than half of the viewBounds are in the area Rect, false otherwise */
+    static boolean isInArea(Rect area, Rect viewBounds) {
+        if (area.isEmpty()) {
+            return true;
+        }
+        sTmpRect.set(area);
+        int left = viewBounds.left;
+        int width = viewBounds.width();
+
+        int intersectStart = Math.max(left, area.left);
+        int intersectEnd = Math.min(left + width, area.right);
+        int intersectAmount = Math.max(0, intersectEnd - intersectStart);
+
+        boolean coversFullStatusBar = area.top <= 0;
+        boolean majorityOfWidth = 2 * intersectAmount > width;
+        return majorityOfWidth && coversFullStatusBar;
+    }
+
+    /** @return true if more than half of the view's area is in the area Rect, false otherwise */
     static boolean isInArea(Rect area, View view) {
         if (area.isEmpty()) {
             return true;
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 0ace8a7..a4b13487 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Draw pattern to install update later"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Device updated Enter PIN to continue."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Device updated Enter password to continue."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated Draw pattern to continue."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated. Draw pattern to continue."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 0ace8a7..a4b13487 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Draw pattern to install update later"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Device updated Enter PIN to continue."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Device updated Enter password to continue."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated Draw pattern to continue."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated. Draw pattern to continue."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 0ace8a7..a4b13487 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Draw pattern to install update later"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Device updated Enter PIN to continue."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Device updated Enter password to continue."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated Draw pattern to continue."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Device updated. Draw pattern to continue."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 3faa7ca..68f22cb 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Debuxa o padrón para instalar a actualización máis tarde"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Actualizouse o dispositivo. Mete o PIN para continuar."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Actualizouse o dispositivo. Mete o contrasinal para continuar."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Actualizouse o dispositivo. Debuxa o padrón para continuar."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Actualizouse o dispositivo. Debuxa o padrón."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index bc66355..00c717c 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"צריך למתוח את קו ביטול הנעילה כדי להתקין את העדכון מאוחר יותר"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"המכשיר עודכן. צריך להזין את קוד האימות כדי להמשיך."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"המכשיר עודכן. צריך להזין את הסיסמה כדי להמשיך."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"המכשיר עודכן. צריך למתוח את קו ביטול הנעילה כדי להמשיך."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"המכשיר עודכן. יש למתוח קו ביטול נעילה כדי להמשיך"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 532253e..0e09fad 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -129,6 +129,6 @@
     <string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"나중에 업데이트를 설치하려면 비밀번호를 입력하세요."</string>
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"나중에 업데이트를 설치하려면 패턴을 그리세요."</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"기기가 업데이트되었습니다. 계속하려면 PIN을 입력하세요."</string>
-    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"기기가 업데이트되었습니다. 계속 진행하려면 비밀번호를 입력하세요."</string>
+    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"기기가 업데이트되었습니다. 계속하려면 비밀번호를 입력하세요."</string>
     <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"기기가 업데이트되었습니다. 계속하려면 패턴을 그리세요."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index e85cf8a..576250b 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -128,7 +128,7 @@
     <string name="kg_prompt_unattended_update_pin" msgid="5979434876768801873">"နောက်ပိုင်းတွင် အပ်ဒိတ်ထည့်သွင်းရန် ပင်နံပါတ်ထည့်ပါ"</string>
     <string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"နောက်ပိုင်းတွင် အပ်ဒိတ်ထည့်သွင်းရန် စကားဝှက်ထည့်ပါ"</string>
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"နောက်ပိုင်းတွင် အပ်ဒိတ်ထည့်သွင်းရန် ပုံဖော်ရေးဆွဲပါ"</string>
-    <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"စက်ပစ္စည်း အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် ပင်နံပါတ်ထည့်ပါ။"</string>
-    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"စက်ပစ္စည်း အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် စကားဝှက်ထည့်ပါ။"</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"စက်ပစ္စည်း အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် ပုံဖော်ရေးဆွဲပါ။"</string>
+    <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် ပင်နံပါတ်ထည့်ပါ။"</string>
+    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် စကားဝှက်ထည့်ပါ။"</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"အပ်ဒိတ်လုပ်ထားသည်။ ရှေ့ဆက်ရန် ပုံဖော်ရေးဆွဲပါ။"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index a236639..1ba4a81 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Teken het patroon om de update later te installeren"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Apparaat geüpdatet. Voer de pincode in om door te gaan."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Apparaat geüpdatet. Voer het wachtwoord in om door te gaan."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Apparaat geüpdatet. Teken het patroon om door te gaan."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Apparaat geüpdatet. Teken patroon om door te gaan."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 4309b56..df28b8d 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -130,5 +130,5 @@
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Desenează pentru a instala actualizarea mai târziu"</string>
     <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Dispozitivul s-a actualizat. Introdu codul PIN pentru a continua."</string>
     <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Dispozitivul s-a actualizat. Introdu parola pentru a continua."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Dispozitivul s-a actualizat. Desenează modelul pentru a continua."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Dispozitiv actualizat. Desenează modelul și continuă."</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 45149a5..62249a1 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -128,7 +128,7 @@
     <string name="kg_prompt_unattended_update_pin" msgid="5979434876768801873">"Введите PIN-код, чтобы установить обновление позже."</string>
     <string name="kg_prompt_unattended_update_password" msgid="8805664437604967210">"Введите пароль, чтобы установить обновление позже."</string>
     <string name="kg_prompt_unattended_update_pattern" msgid="8580479377489546091">"Введите графический ключ, чтобы установить обновление позже."</string>
-    <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Устройство обновлено. Введите PIN-код."</string>
-    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Устройство обновлено. Введите пароль."</string>
-    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Устройство обновлено. Введите графический ключ."</string>
+    <string name="kg_prompt_after_update_pin" msgid="7051709651908643013">"Устройство обновлено. Чтобы продолжить, введите PIN-код."</string>
+    <string name="kg_prompt_after_update_password" msgid="153703052501352094">"Устройство обновлено. Чтобы продолжить, введите пароль."</string>
+    <string name="kg_prompt_after_update_pattern" msgid="1484084551298241992">"Устройство обновлено. Чтобы продолжить, введите графический ключ."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 24846d9..f68dd7b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Stoor tans skermskoot in werkprofiel …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kon nie skermkiekie stoor nie"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Toestel moet ontsluit word voordat skermkiekie gestoor kan word"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer weer skermkiekie neem"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Kan nie skermkiekie stoor nie"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Saai tans uit"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Onbenoemde toestel"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Geen toestelle beskikbaar nie"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi is nie gekoppel nie"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleuromkering"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurregstelling"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans vinnig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klik die pylknoppie om die gemeenskaplike tutoriaal te begin"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle programme en data in hierdie sessie sal uitgevee word."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 23def28..20a8120 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ቅጽበታዊ ገፅ እይታን ወደ የስራ መገለጫ በማስቀመጥ ላይ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገፅ ዕይታ ተቀምጧል"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ቅጽበታዊ ገፅ ዕይታን ማስቀመጥ አልተቻለም"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ቅጽበታዊ ገፅ ዕይታ ከመቀመጡ በፊት መሣሪያ መከፈት አለበት"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ቅጽበታዊ ገፅ ዕይታን እንደገና ማንሳት ይሞክሩ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ቅጽበታዊ ገፅ እይታን ማስቀመጥ አልተቻለም"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"በመውሰድ ላይ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ያልተሰየመ መሣሪያ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ምንም መሣሪያዎች አይገኙም"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi አልተገናኘም"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ብሩህነት"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ተቃራኒ ቀለም"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"የቀለም ማስተካከያ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"የጋራ አጋዥ ሥልጠናን ለመጀመር የቀስት አዝራሩ ላይ ጠቅ ያድርጉ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ተጠቃሚ ቀይር"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ወደታች ተጎታች ምናሌ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"በዚህ ክፍለ-ጊዜ ውስጥ ያሉ ሁሉም መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 80d63a2..03e019c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"جارٍ حفظ لقطة الشاشة في الملف الشخصي للعمل…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"تعذّر حفظ لقطة الشاشة"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"يجب أن يتم فتح قفل الجهاز قبل حفظ لقطة الشاشة."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"جرّب أخذ لقطة الشاشة مرة أخرى"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"يتعذّر حفظ لقطة الشاشة."</string>
@@ -159,7 +161,7 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"النقش غير صحيح."</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"كلمة مرور غير صحيحة"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"تم إجراء عدد كبير جدًا من المحاولات غير الصحيحة.\nأعد المحاولة خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
-    <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"الطوارئ"</string>
+    <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"طوارئ"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"يُرجى إعادة المحاولة. المحاولة <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> من <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>"</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"سيتم حذف بياناتك"</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف بيانات هذا الجهاز."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"جارٍ الإرسال"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"جهاز لا يحمل اسمًا"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"لا يتوفر أي جهاز"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"‏لم يتم الاتصال بشبكة Wi-Fi."</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"السطوع"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"قلب الألوان"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحيح الألوان"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"انقر على زر السهم لبدء الدليل التوجيهي العام."</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تبديل المستخدم"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"القائمة المنسدلة"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"سيتم حذف كل التطبيقات والبيانات في هذه الجلسة."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c845773..014e3b7 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"কৰ্মস্থানৰ প্ৰ’ফাইলত স্ক্ৰীনশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীনশ্বট ছেভ কৰা হ’ল"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্ৰীনশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্ৰীনশ্বট ছেভ কৰিবলৈ ডিভাইচটো আনলক কৰিবই লাগিব"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"স্ক্ৰীনশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"স্ক্ৰীনশ্বট ছেভ কৰিব নোৱাৰি"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"কাষ্টিং"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"নাম নথকা ডিভাইচ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"কোনো ডিভাইচ নাই"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ৱাই-ফাইৰ সৈতে সংযোগ হৈ থকা নাই"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ৰং বিপৰীতকৰণ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ৰং শুধৰণী"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ কাঁড়চিহ্নৰ বুটামটোত ক্লিক কৰক"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুল-ডাউনৰ মেনু"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই ছেশ্বনৰ আটাইবোৰ এপ্ আৰু ডেটা মচা হ\'ব।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5aa26ba..d34ad9a 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"İş profili skrinşotu saxlanılır…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinşotu yadda saxlamaq alınmadı"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinşotu saxlamazdan əvvəl cihaz kiliddən çıxarılmalıdır"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skrinşotu yenidən çəkin"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Skrinşotu yadda saxlamaq mümkün olmadı"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Yayım"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Adsız cihaz"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Heç bir cihaz əlçatan deyil"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi qoşulu deyil"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaqlıq"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rəng inversiyası"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Rəng korreksiyası"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"İcma təlimatını başlatmaq üçün ox düyməsinə klikləyin"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aşağı çəkilən menyu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu sessiyada bütün tətbiqlər və data silinəcək."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cd36884..2b19e36 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Snimak ekrana se čuva na poslovnom profilu…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Čuvanje snimka ekrana nije uspelo"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora da bude otključan da bi snimak ekrana mogao da se sačuva"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probajte da ponovo napravite snimak ekrana"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Čuvanje snimka ekrana nije uspelo"</string>
@@ -101,8 +103,8 @@
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Želite da započnete snimanje?"</string>
-    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju dok snimate. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
-    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kada snimate aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
+    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju dok snimate. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
+    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kada snimate aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Započni snimanje"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimaj zvuk"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk uređaja"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Prebacivanje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Neimenovani uređaj"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nije dostupan nijedan uređaj"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"WiFi nije povezan"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Osvetljenost"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcija boja"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknite na dugme sa strelicom da biste započeli zajednički vodič"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
@@ -418,17 +422,17 @@
     <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikacija"</string>
     <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Delite ili snimite aplikaciju"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Želite da počnete snimanje ili prebacivanje pomoću aplikacije <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada delite, snimate ili prebacujete, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
-    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"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. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada delite, snimate ili prebacujete, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"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. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
     <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string>
     <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućila ovu opciju"</string>
     <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite da započnete prebacivanje?"</string>
-    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
-    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
     <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Započni prebacivanje"</string>
     <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Želite da počnete da delite?"</string>
-    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kada delite, snimate ili prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
-    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kada delite, snimate ili prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kada delite, snimate ili prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kada delite, snimate ili prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i videima."</string>
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Pokreni"</string>
     <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Deljenje se zaustavlja kada menjate aplikacije"</string>
     <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Deli ovu aplikaciju"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 1b03c8b..301a042 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Захаванне здымка экрана ў працоўны профіль…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не атрымалася зрабіць здымак экрана"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Перад захаваннем здымка экрана трэба разблакіраваць прыладу"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Не ўдалося захаваць здымак экрана"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Ідзе перадача"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Прылада без назвы"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Няма даступных прылад"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Няма падключэння да Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркасць"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія колераў"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Карэкцыя колераў"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе хуткая зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Націсніце кнопку са стрэлкай, каб азнаёміцца з дапаможнікам"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Перайсці да іншага карыстальніка"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"высоўнае меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 4ed1ad9..29f9d9e9 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Екранната снимка се запазва в служебния профил…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не можа да се запази екранна снимка"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"За да бъде запазена екранната снимка, устройството трябва да бъде отключено"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Опитайте да направите екранна снимка отново"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Екранната снимка не може да се запази"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Предава се"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Устройство без име"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Няма налични устройства"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Не е установена връзка с Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркост"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инвертиране на цветовете"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекция на цветове"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Кликнете върху бутона със стрелка, за да стартирате общия урок"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Превключване между потребителите"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падащо меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Всички приложения и данни в тази сесия ще бъдат изтрити."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 426d38d..c2662d1 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"অফিস প্রোফাইলে স্ক্রিনশট সেভ করা হচ্ছে…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্রিনশট সেভ করা যায়নি"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্রিনশট সেভ করার আগে ডিভাইসটি অবশ্যই আনলক করতে হবে"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"স্ক্রিনশট সেভ করা যায়নি"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"কাস্ট করা হচ্ছে"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"নামবিহীন ডিভাইস"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"কোনো ডিভাইস উপলব্ধ নয়"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ওয়াই-ফাই কানেক্ট করা নেই"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"কালার ইনভার্সন"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"রঙ সংশোধন"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্রুত চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"কমিউনিটি টিউটোরিয়াল চালু করতে তীরচিহ্ন বোতামে ক্লিক করুন"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ব্যবহারকারী পাল্টে দিন"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"পুলডাউন মেনু"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"এই সেশনের সব অ্যাপ ও ডেটা মুছে ফেলা হবে।"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4eed7b89..8d10454 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pohranjivanje snimka ekrana na radni profil…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nije moguće sačuvati snimak ekrana"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Morate otključati uređaj da možete sačuvati snimak ekrana"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo snimiti ekran"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nije moguće sačuvati snimak ekrana"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Prebacivanje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Neimenovani uređaj"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nema dostupnih uređaja"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"WiFi mreža nije povezana"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Osvjetljenje"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ispravka boja"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknite na dugme sa strelicom da pokrenete zajednički vodič"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zamijeni korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b55a79a..683c034 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"S\'està desant la captura al perfil de treball…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No s\'ha pogut desar la captura de pantalla"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositiu ha d\'estar desbloquejat abans que la captura de pantalla es pugui desar"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"No es pot desar la captura de pantalla"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"En emissió"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositiu sense nom"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"No hi ha cap dispositiu disponible."</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"La Wi‑Fi no està connectada"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillantor"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversió de colors"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correcció de color"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant ràpidament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Fes clic al botó de la fletxa per iniciar el tutorial de la comunitat"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 05b0419..cbbf9df 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ukládání snímku obrazovky do pracovního profilu…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímek obrazovky se nepodařilo uložit"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Aby bylo možné uložit screenshot, zařízení musí být odemknuto"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zkuste snímek pořídit znovu"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Snímek obrazovky se nepodařilo uložit"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Odesílání"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nepojmenované zařízení"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nejsou dostupná žádná zařízení"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Není připojena Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Převrácení barev"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekce barev"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rychlé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknutím na tlačítko s šipkou spustíte společný výukový program"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5971034..57124bd 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Gemmer screenshot på din arbejdsprofil…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshottet kunne ikke gemmes"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheden skal være låst op, før du kan gemme screenshots"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv at tage et screenshot igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Dit screenshot kunne ikke gemmes."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Caster"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Enhed uden navn"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Der er ingen tilgængelige enheder"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Manglende Wi-Fi-forbindelse"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ombytning af farver"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farvekorrigering"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader hurtigt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klik på pilen for at starte den fælles vejledning"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skift bruger"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullemenu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps og data i denne session slettes."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c773f71..8c308b9 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Screenshot wird in Arbeitsprofil gespeichert…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshot konnte nicht gespeichert werden"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Damit Screenshots gespeichert werden können, muss das Gerät entsperrt sein"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Versuche noch einmal, den Screenshot zu erstellen"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Screenshot kann nicht gespeichert werden"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Wird übertragen"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Unbenanntes Gerät"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Keine Geräte verfügbar"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"WLAN nicht verbunden"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helligkeit"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Farbumkehr"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farbkorrektur"</string>
@@ -395,6 +398,8 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <!-- no translation found for communal_tutorial_indicator_text (700342473477865107) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b6c95aa..69d877b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Αποθήκευση στιγμιότ. οθόνης στο προφίλ εργασίας…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Μη δυνατή αποθήκευση του στιγμιότυπου οθόνης"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Η συσκευή πρέπει να ξεκλειδωθεί για να αποθηκευτεί το στιγμιότυπο οθόνης."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Δεν είναι δυνατή η αποθήκευση στιγμιότυπου οθόνης."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Μετάδοση"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Ανώνυμη συσκευή"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Δεν υπάρχουν διαθέσιμες συσκευές"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Το Wi-Fi δεν είναι συνδεδεμένο"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Φωτεινότητα"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Αντιστροφή χρωμάτων"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Διόρθωση χρωμάτων"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Γρήγορη φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Κάντε κλικ στο κουμπί βέλους για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Εναλλαγή χρήστη"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"αναπτυσσόμενο μενού"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Όλες οι εφαρμογές και τα δεδομένα αυτής της περιόδου σύνδεσης θα διαγραφούν."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 6c2b230..645f70e 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Can\'t save screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Unnamed device"</string>
     <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>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <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>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Click on the arrow button to start the communal tutorial"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 0e282ff..f05d3c0 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -76,6 +76,7 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <string name="screenshot_failed_external_display_indication" msgid="6555673132061101936">"External Display"</string>
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Can\'t save screenshot"</string>
@@ -280,7 +281,7 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Unnamed device"</string>
     <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_cast_no_network" msgid="3863016850468559522">"No Wi‑Fi or Ethernet connection"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Color inversion"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Color correction"</string>
@@ -395,6 +396,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Click on the arrow button to start the communal tutorial"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 6c2b230..645f70e 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Can\'t save screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Unnamed device"</string>
     <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>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <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>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Click on the arrow button to start the communal tutorial"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 6c2b230..645f70e 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Can\'t save screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Unnamed device"</string>
     <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>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <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>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Click on the arrow button to start the communal tutorial"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Switch user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"All apps and data in this session will be deleted."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 1f3ab27..4934d73 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -76,6 +76,7 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎Saving screenshot to work profile…‎‏‎‎‏‎"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎Screenshot saved‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎Couldn\'t save screenshot‎‏‎‎‏‎"</string>
+    <string name="screenshot_failed_external_display_indication" msgid="6555673132061101936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎External Display‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎Device must be unlocked before screenshot can be saved‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎Try taking screenshot again‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎Can\'t save screenshot‎‏‎‎‏‎"</string>
@@ -280,7 +281,7 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎Casting‎‏‎‎‏‎"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎Unnamed device‎‏‎‎‏‎"</string>
     <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_cast_no_network" msgid="3863016850468559522">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎No Wi‑Fi or Ethernet connection‎‏‎‎‏‎"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎Brightness‎‏‎‎‏‎"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎Color inversion‎‏‎‎‏‎"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎Color correction‎‏‎‎‏‎"</string>
@@ -395,6 +396,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎Click on the arrow button to start the communal tutorial‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎Switch user‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎pulldown menu‎‏‎‎‏‎"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎All apps and data in this session will be deleted.‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 52514d2..fa1a3f5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Guardando cap. de pantalla en perfil de trabajo…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No se pudo guardar la captura de pantalla"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe estar desbloqueado para poder guardar la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a hacer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"No se pudo guardar la captura de pantalla"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Transmitiendo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sin nombre"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"No hay dispositivos disponibles"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Red Wi-Fi no conectada"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corregir colores"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Haz clic en el botón de flecha para iniciar el instructivo comunal"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4a3c064..005895b 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Guardando captura en el perfil de trabajo…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"No se ha podido guardar la captura de pantalla"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe desbloquearse para que se pueda guardar la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a intentar hacer la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"No se puede guardar la captura de pantalla"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Enviando"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sin nombre"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"No hay dispositivos disponibles"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi‑Fi no conectado"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección de color"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Haz clic en el botón de la flecha para iniciar el tutorial de la comunidad"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar de usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán todas las aplicaciones y datos de esta sesión."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 08b489d..b4463d2 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ekraanipildi salvestamine tööprofiilile …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekraanipilti ei õnnestunud salvestada"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enne ekraanipildi salvestamist tuleb seade avada"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Proovige ekraanipilt uuesti jäädvustada"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ekraanipilti ei saa salvestada"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Osatäitjad"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nimeta seade"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Ühtegi seadet pole saadaval"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"WiFi-ühendus puudub"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Heledus"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Värvide ümberpööramine"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värviparandus"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Ühise õpetuse käivitamiseks klõpsake noolenuppu"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kasutaja vahetamine"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rippmenüü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 19495bc..6701a77 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pantaila-argazkia laneko profilean gordetzen…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ezin izan da gorde pantaila-argazkia"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pantaila-argazkia gordetzeko, gailuak desblokeatuta egon beharko du"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Saiatu berriro pantaila-argazkia ateratzen"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ezin da gorde pantaila-argazkia"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Igortzen"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Izenik gabeko gailua"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Ez dago gailurik erabilgarri"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Ez zaude konektatuta wifi-sarera"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Distira"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Koloreen alderantzikatzea"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koloreen zuzenketa"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Tutorial komuna hasteko, sakatu geziaren botoia"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Aldatu erabiltzailea"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"zabaldu menua"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Saioko aplikazio eta datu guztiak ezabatuko dira."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 68f6c1d..705cc7c 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"درحال ذخیره کردن نماگرفت در نمایه کاری…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"نماگرفت ذخیره شد"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"نماگرفت ذخیره نشد"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"برای ذخیره کردن نماگرفت، قفل دستگاه باید باز باشد"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"نماگرفت ذخیره نمی‌شود"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"در حال فرستادن"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"دستگاه بدون نام"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"دستگاهی موجود نیست"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"‏Wi-Fi وصل نیست"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"روشنایی"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"وارونگی رنگ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحیح رنگ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن سریع • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"برای شروع آموزش گام‌به‌گام عمومی، روی دکمه جهت‌نما کلیک کنید"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"تغییر کاربر"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"منوی پایین‌پر"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"همه برنامه‌ها و داده‌های این جلسه حذف خواهد شد."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 934abad..d1c583b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Kuvakaappausta tallennetaan työprofiiliin…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kuvakaappauksen tallennus epäonnistui"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Laitteen lukitus täytyy avata ennen kuin kuvakaappaus voidaan tallentaa"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Yritä ottaa kuvakaappaus uudelleen."</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Kuvakaappausta ei voi tallentaa"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Lähetetään"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nimetön laite"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Laitteita ei ole käytettävissä"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fiä ei ole yhdistetty"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kirkkaus"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Käänteiset värit"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värinkorjaus"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu nopeasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Aloita yhteisöesittely klikkaamalla nuolipainiketta"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Vaihda käyttäjää"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"alasvetovalikko"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Kaikki sovellukset ja tämän istunnon tiedot poistetaan."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index fe90569..366d715 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sauv. de la capture dans le profil prof. en cours…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"L\'appareil doit être déverrouillé avant qu\'une capture d\'écran puisse être enregistrée"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de faire une autre capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Impossible d\'enregistrer la capture d\'écran"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Appareil sans nom"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Aucun appareil à proximité"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Non connecté au Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Cliquez sur le bouton de flèche pour démarrer le tutoriel communautaire"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 27a4bb6..8a51092 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Enregistrement de capture d\'écran dans profil pro…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Vous devez déverrouiller l\'appareil pour que la capture d\'écran soit enregistrée"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Impossible d\'enregistrer la capture d\'écran"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Appareil sans nom"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Aucun appareil disponible."</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi non connecté"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge rapide • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Cliquer sur la flèche pour démarrer le tutoriel collectif"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu déroulant"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toutes les applications et les données de cette session seront supprimées."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 2056c2f..e8aa65f 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Gardando captura de pantalla no perfil de traballo"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Non se puido gardar a captura de pantalla"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que se poida gardar a captura de pantalla, o dispositivo debe estar desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Volve tentar crear unha captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Non se puido gardar a captura de pantalla"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Emitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sen nome"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Non hai dispositivos dispoñibles"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"A wifi non está conectada"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversión da cor"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección da cor"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rapidamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Fai clic no botón da frecha para iniciar o titorial comunitario"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú despregable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Eliminaranse todas as aplicacións e datos desta sesión."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 84be50a..15b1b44 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ઑફિસની પ્રોફાઇલમાં સ્ક્રીનશૉટ સાચવી રહ્યાં છીએ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"સ્ક્રીનશૉટ સાચવી શક્યાં નથી"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"સ્ક્રીનશૉટ સાચવવામાં આવે તે પહેલાં ડિવાઇસને અનલૉક કરવું જરૂરી છે"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"કાસ્ટ કરી રહ્યાં છે"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"અનામાંકિત ઉપકરણ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"કોઈ ઉપકરણો ઉપલબ્ધ નથી"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"વાઇ-ફાઇ કનેક્ટ નથી"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"તેજ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"વિપરીત રંગમાં બદલવું"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"રંગ સુધારણા"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ઍરો બટન પર ક્લિક કરો"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"વપરાશકર્તા સ્વિચ કરો"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"પુલડાઉન મેનૂ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"આ સત્રમાંની તમામ ઍપ અને ડેટા કાઢી નાખવામાં આવશે."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 2b0019f..d63f5cb 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"स्क्रीनशॉट, वर्क प्रोफ़ाइल में सेव किया जा रहा है…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव नहीं किया जा सका"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव करने के लिए डिवाइस का अनलॉक होना ज़रूरी है"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"स्क्रीनशॉट को सेव नहीं किया जा सकता"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"कास्टिंग"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"अनाम डिवाइस"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"कोई डिवाइस उपलब्ध नहीं"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"वाई-फ़ाई कनेक्ट नहीं है"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"स्क्रीन की रोशनी"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"रंग बदलने की सुविधा"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग में सुधार करने की सुविधा"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तेज़ चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, तीर के निशान वाले बटन पर क्लिक करें"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"उपयोगकर्ता बदलें"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेन्यू"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"इस सेशन के सभी ऐप्लिकेशन और डेटा को हटा दिया जाएगा."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 23899fc..c3ea5ff2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Spremanje snimke zaslona na poslovni profil…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snimka zaslona nije spremljena"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora biti otključan da bi se snimka zaslona mogla spremiti"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo napraviti snimku zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nije moguće spremiti snimku zaslona"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Emitiranje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Uređaj bez naziva"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nema dostupnih uređaja"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi mreža nije povezana"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svjetlina"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcija boja"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • brzo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknite gumb sa strelicom da biste pokrenuli zajednički vodič"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index e5b17d9..c894232 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Képernyőkép mentése a munkaprofilba…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nem sikerült a képernyőkép mentése"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Az eszközt fel kell oldani a képernyőkép mentése előtt"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Próbálja meg újra elkészíteni a képernyőképet"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nem lehetséges a képernyőkép mentése"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Átküldés"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Név nélküli eszköz"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nem áll rendelkezésre eszköz"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Nem kapcsolódik Wi‑Fi-hálózathoz"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Fényerő"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Színek invertálása"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Színjavítás"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Gyors töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kattintson a nyíl gombra a közösségi útmutató elindításához"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Felhasználóváltás"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"lehúzható menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4a1c291..67d3886 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Սքրինշոթը պահվում է աշխատանքային պրոֆիլում…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Չհաջողվեց պահել սքրինշոթը"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Սքրինշոթը պահելու համար ապակողպեք սարքը։"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Փորձեք նորից"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Չհաջողվեց պահել սքրինշոթը"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Հեռարձակում"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Անանուն սարք"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Հասանելի սարքեր չկան"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi-ը միացված չէ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Պայծառություն"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Գունաշրջում"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Գունաշտկում"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Սեղմեք սլաքի կոճակը՝ ուղեցույցը գործարկելու համար"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Անջատել օգտվողին"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"իջնող ընտրացանկ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 18a7668..b1feb48 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Menyimpan screenshot ke profil kerja …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Perangkat harus dibuka kuncinya agar screenshot dapat disimpan"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Coba ambil screenshot lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Tidak dapat menyimpan screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Melakukan transmisi"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Perangkat tanpa nama"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Perangkat tak tersedia"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi‑Fi tidak terhubung"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversi warna"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koreksi warna"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klik tombol panah untuk memulai tutorial komunal"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pulldown"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 70bed46..9ff9c1a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Vistar skjámynd á vinnusnið…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekki var hægt að vista skjámynd"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Taka verður tækið úr lás áður en hægt er að vista skjámynd"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prófaðu að taka skjámynd aftur"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ekki er hægt að vista skjámynd"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Sendir út"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Ónefnt tæki"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Engin tæki til staðar"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi ekki tengt"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Birtustig"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Umsnúningur lita"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Litaleiðrétting"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hraðhleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Smelltu á örvahnappinn til að hefja samfélagsleiðsögnina"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index baffdb9..7fafa62 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvataggio screenshot nel profilo di lavoro…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossibile salvare lo screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"È necessario sbloccare il dispositivo per poter salvare lo screenshot"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Riprova ad acquisire lo screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Impossibile salvare lo screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"In trasmissione"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo senza nome"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nessun dispositivo disponibile"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Nessuna connessione Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosità"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversione dei colori"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correzione del colore"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica veloce • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Fai clic sul pulsante Freccia per iniziare il tutorial della community"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 968a982..ced5895 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"צילום המסך נשמר בפרופיל העבודה…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"לא ניתן היה לשמור את צילום המסך"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"כדי שצילום המסך יישמר, צריך לבטל את הנעילה של המכשיר"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"אפשר לצלם שוב את המסך"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"לא ניתן לשמור את צילום המסך"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"‏מתבצעת העברה (cast)"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"מכשיר ללא שם"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"אין מכשירים זמינים"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"‏אין חיבור ל-Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"בהירות"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"היפוך צבעים"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"תיקון צבע"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"אפשר ללחוץ על לחצן החץ כדי להפעיל את המדריך המשותף"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"החלפת משתמש"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"תפריט במשיכה למטה"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"כל האפליקציות והנתונים בסשן הזה יימחקו."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 798d42a..f5d5b74 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"スクリーンショットを仕事用プロファイルに保存中…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"スクリーンショット保存エラー"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"スクリーンショットを保存するには、デバイスのロックを解除する必要があります"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"スクリーンショットを保存できません"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"キャストしています"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"名前のないデバイス"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"利用可能なデバイスがありません"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi 未接続"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"画面の明るさ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"色反転"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色補正"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 急速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"矢印ボタンをクリックすると、コミュニティ チュートリアルが開始します"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ユーザーを切り替える"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"プルダウン メニュー"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index f21a2a4..ae93966 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"მიმდინარეობს ეკრანის ანაბეჭდის შენახვა სამუშაო პროფილში…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"მოწყობილობა უნდა განიბლოკოს ეკრანის ანაბეჭდის შენახვა რომ შეძლოთ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ეკრანის ანაბეჭდის შენახვა ვერ ხერხდება"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"გადაიცემა"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"უსახელო მოწყობილობა"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"მოწყობილობები მიუწვდომელია"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi არ არის დაკავშირებული"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"განათება"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ფერთა ინვერსია"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ფერთა კორექცია"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • სწრაფად იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"დააწკაპუნეთ ისრის ღილაკზე, რათა დაიწყოთ საერთო სახელმძღვანელო"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"მომხმარებლის გადართვა"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ჩამოშლადი მენიუ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ამ სესიის ყველა აპი და მონაცემი წაიშლება."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 746c02e..8c8efd1 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Скриншот жұмыс профиліне сақталып жатыр…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сақталмады"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншот сақталуы үшін, құрылғы құлпын ашу керек."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Қайта скриншот жасап көріңіз"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Скриншотты сақтау мүмкін емес."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Трансляциялануда"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Атаусыз құрылғы"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Құрылғылар қол жетімді емес"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi желісіне жалғанбаған"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарықтығы"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түс инверсиясы"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түсті түзету"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядтау • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Жалпы оқулықты ашу үшін бағыт түймесін басыңыз."</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Пайдаланушыны ауыстыру"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ашылмалы мәзір"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданба мен дерек жойылады."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 9f3b991..cefdd27 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"កំពុងរក្សាទុករូបថតអេក្រង់ទៅកម្រងព័ត៌មានការងារ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់បានទេ"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ត្រូវតែ​ដោះសោ​ឧបករណ៍​ជាមុនសិន ទើបអាច​រក្សាទុក​រូបថតអេក្រង់​បាន"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"សាកល្បង​ថតរូបថត​អេក្រង់​ម្តងទៀត"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"មិនអាច​រក្សាទុករូបថត​អេក្រង់បានទេ"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"ការ​ចាត់​ថ្នាក់"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ឧបករណ៍​​ដែល​មិន​មាន​ឈ្មោះ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"មិន​មាន​ឧបករណ៍​ដែល​អាច​ប្រើ​បាន"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"មិនមាន​ការតភ្ជាប់ Wi-Fi ទេ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ពន្លឺ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ការបញ្ច្រាស​ពណ៌"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ការ​កែតម្រូវ​ពណ៌"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម​យឺត • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"ចុចលើប៊ូតុងសញ្ញាព្រួញ ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ប្ដូរ​អ្នក​ប្រើ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ម៉ឺនុយ​ទាញចុះ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យ​ទាំងអស់​ក្នុង​វគ្គ​នេះ​នឹង​ត្រូវ​លុប។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 79eef72..6ec02ca 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸುವ ಮೊದಲು ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಬೇಕು"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ಹೆಸರಿಸದಿರುವ ಸಾಧನ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ಯಾವುದೇ ಸಾಧನಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ವೈ-ಫೈ ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ಪ್ರಕಾಶಮಾನ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ಕಲರ್ ಇನ್‍ವರ್ಶನ್"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"ಸಮುದಾಯದ ಟುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಆ್ಯರೋ ಬಟನ್ ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ಪುಲ್‌ಡೌನ್ ಮೆನು"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ಈ ಸೆಷನ್‌ನಲ್ಲಿನ ಎಲ್ಲ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 7985e4c..69525ee 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"직장 프로필에 스크린샷 저장 중…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"스크린샷을 저장할 수 없음"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"스크린샷을 저장하려면 기기를 잠금 해제해야 합니다."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"스크린샷을 다시 찍어 보세요."</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"스크린샷을 저장할 수 없습니다."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"전송 중"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"이름이 없는 기기"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"사용 가능한 기기가 없습니다."</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi가 연결되지 않음"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"밝기"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"색상 반전"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"색상 보정"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"공동 튜토리얼을 시작하려면 화살표 버튼을 클릭하세요."</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"사용자 전환"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"풀다운 메뉴"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index ded1f75..400afed 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Скриншот жумуш профилине сакталууда…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сакталган жок"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншотту сактоо үчүн түзмөктүн кулпусун ачуу керек"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Скриншотту кайра тартып көрүңүз"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Скриншот сакталган жок"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Тышкы экранга чыгарылууда"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Аты жок түзмөк"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Жеткиликтүү түзмөктөр жок"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi туташкан жок"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарыктыгы"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түстөрдү инверсиялоо"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түстөрдү тууралоо"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Жалпы үйрөткүчтү иштетүү үчүн жебе баскычын басыңыз"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Колдонуучуну которуу"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ылдый түшүүчү меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана аларга байланыштуу нерселер өчүрүлөт."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 1e61b8a..b66e6dc 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ກຳລັງບັນທຶກຮູບໜ້າຈໍໃສ່ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ບໍ່ສາມາດບັນທຶກຮູບໜ້າຈໍໄດ້"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ຈະຕ້ອງປົດລັອກອຸປະກອນກ່ອນບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ບໍ່ສາມາດບັນທຶກຮູບໜ້າຈໍໄດ້"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"​ກຳ​ລັງ​ສົ່ງ​ສັນ​ຍານ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"​ອຸ​ປະ​ກອນບໍ່​ມີ​ຊື່"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"​ບໍ່​ມີ​ອຸ​ປະ​ກອນ​ທີ່​ສາ​ມາດ​ໃຊ້​ໄດ້"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ບໍ່ໄດ້ເຊື່ອມຕໍ່ Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ຄວາມແຈ້ງ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ການປີ້ນສີ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ການແກ້ໄຂສີ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບໄວ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"ຄລິກໃສ່ປຸ່ມລູກສອນເພື່ອເລີ່ມຕົ້ນສອນການນຳໃຊ້ຊຸມຊົນ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ສະຫຼັບຜູ້ໃຊ້"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ເມນູແບບດຶງລົງ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯ​ແລະ​ຂໍ້​ມູນ​ທັງ​ໝົດ​ໃນ​ເຊດ​ຊັນ​ນີ້​ຈະ​ຖືກ​ລຶບ​ອອກ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 06c1369..955fe67 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Išsaugoma ekrano kopija darbo profilyje…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrano kopijos išsaugoti nepavyko"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Įrenginys turi būti atrakintas, kad būtų galima išsaugoti ekrano kopiją"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pabandykite padaryti ekrano kopiją dar kartą"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ekrano kopijos išsaugoti nepavyko"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Perduodama"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Įrenginys be pavadinimo"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nėra pasiekiamų įrenginių"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"„Wi-Fi“ neprijungtas"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Šviesumas"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Spalvų inversija"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Spalvų taisymas"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sparčiai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Spustelėkite rodyklės mygtuką, kad paleistumėte bendruomenės mokomąją medžiagą"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index fdf3028..16cef4b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Notiek ekrānuzņēmuma saglabāšana darba profilā…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrānuzņēmumu neizdevās saglabāt."</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Lai varētu saglabāt ekrānuzņēmumu, ierīcei ir jābūt atbloķētai."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nevar saglabāt ekrānuzņēmumu"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Notiek apraide…"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nenosaukta ierīce"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nav pieejamu ierīču."</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Nav izveidots savienojums ar Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Spilgtums"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Krāsu inversija"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Krāsu korekcija"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Noklikšķiniet uz bultiņas pogas, lai palaistu kopienas pamācību."</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mainīt lietotāju"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"novelkamā izvēlne"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tiks dzēstas visas šīs sesijas lietotnes un dati."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 80ef7bb..8babe8c 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Се зачувува слика од екранот на вашиот работен профил…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не може да се зачува слика од екранот"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уредот мора да биде отклучен за да може да се зачува слика од екранот"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Повторно обидете се да направите слика од екранот"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Не може да се зачува слика од екранот"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Емитување"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Неименуван уред"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Нема достапни уреди"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Нема Wi-Fi врска"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветленост"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија на боите"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција на боите"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни брзо • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Кликнете на копчето со стрелка за да го започнете заедничкото упатство"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Промени го корисникот"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"паѓачко мени"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијата ќе се избришат."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 5b1c80f..c5b6536 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനായില്ല"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഉപകരണം അൺലോക്ക് ചെയ്തിരിക്കണം"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"കാസ്റ്റുചെയ്യുന്നു"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"പേരിടാത്ത ഉപകരണം"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ഉപകരണങ്ങളൊന്നും ലഭ്യമല്ല"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"വൈഫൈ കണക്റ്റ് ചെയ്‌തിട്ടില്ല"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"തെളിച്ചം"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"നിറം വിപരീതമാക്കൽ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"നിറം ശരിയാക്കൽ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ അമ്പടയാള ബട്ടണിൽ ക്ലിക്ക് ചെയ്യുക"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ഉപയോക്താവ് മാറുക"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"പുൾഡൗൺ മെനു"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ഈ സെഷനിലെ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3f65931..b083c66 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Дэлгэцийн агшныг ажлын профайлд хадгалж байна…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Дэлгэцээс дарсан зургийг хадгалж чадсангүй"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Дэлгэцийн агшныг хадгалах боломжтой болохоос өмнө төхөөрөмжийн түгжээг тайлах ёстой"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Дэлгэцийн агшныг хадгалах боломжгүй"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Дамжуулж байна"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Нэргүй төхөөрөмж"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Төхөөрөмж байхгүй"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi-д холбогдоогүй байна"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Тодрол"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Өнгө хувиргалт"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Өнгө тохируулга"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Хурдтай цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Нийтийн практик хичээлийг эхлүүлэхийн тулд суман товчийг товшино уу"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Хэрэглэгчийг сэлгэх"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"эвхмэл цэс"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 238aaca..5d9f67e 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"कार्य प्रोफाइलवर स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव्ह करू शकलो नाही"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव्ह करण्याआधी डिव्हाइस अनलॉक करणे आवश्यक आहे"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"स्क्रीनशॉट सेव्ह करू शकत नाही"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"कास्ट करत आहे"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"निनावी डिव्हाइस"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"कोणतेही डिव्हाइसेस उपलब्ध नाहीत"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"वाय-फाय नाही"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"चमक"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्व्हर्जन"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग सुधारणा"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी ॲरो बटणावर क्लिक करा"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"वापरकर्ता स्विच करा"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनू"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अ‍ॅप्स आणि डेटा हटवला जाईल."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8c764f1..10e9859c 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Menyimpan tangkapan skrin ke profil kerja…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan tangkapan skrin"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Peranti mesti dibuka kunci sebelum tangkapan skrin dapat disimpan"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Cuba ambil tangkapan skrin sekali lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Tidak dapat menyimpan tangkapan skrin"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Menghantar"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Peranti tidak bernama"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Tiada peranti tersedia"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi tidak disambungkan"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Penyongsangan warna"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pembetulan warna"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klik butang anak panah untuk memulakan tutorial umum"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 883b9e9..dddc2fa 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"အလုပ်ပရိုဖိုင်တွင် ဖန်သားပြင်ဓာတ်ပုံ သိမ်းနေသည်…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"မျက်နှာပြင်ပုံကို သိမ်း၍မရပါ"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ဖန်သားပြင်ဓာတ်ပုံကို မသိမ်းမီ စက်ပစ္စည်းကို လော့ခ်ဖွင့်ထားရမည်"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်း၍မရပါ"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"ကာစ်တင်"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"အမည်မတပ် ကိရိယာ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ကိရိယာများ မရှိ"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi ချိတ်ဆက်ထားခြင်းမရှိပါ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"အလင်းတောက်ပမှု"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"အရောင်ပြောင်းပြန်ပြုလုပ်ရန်"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"အရောင် အမှန်ပြင်ခြင်း"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် မြားခလုတ်ကို နှိပ်ပါ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ဆွဲချမီနူး"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 53a4c52..ff32177 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Lagrer skjermdumpen i jobbprofilen …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kunne ikke lagre skjermdump"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheten må være låst opp før skjermdumpen kan lagres"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv å ta skjermdump på nytt"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Kan ikke lagre skjermdumpen"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Enhet uten navn"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Ingen enheter er tilgjengelige"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wifi er ikke tilkoblet"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Fargeinvertering"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Fargekorrigering"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader raskt • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klikk på pilen for å starte fellesveiledningen"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullegardinmeny"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 3b31b3a..61e52bd 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"कार्य प्रोफाइलमा स्क्रिनसट सेभ गरिँदै छ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सेभ गरियो"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"डिभाइस अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"प्रसारण गर्दै"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"बेनाम उपकरण"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"कुनै उपकरणहरू उपलब्ध छैन"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi कनेक्ट गरिएको छैन"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"उज्यालपन"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्भर्सन"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"कलर करेक्सन"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • छिटो चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"कम्युनल ट्युटोरियल सुरु गर्न एरो बटनमा क्लिक गर्नुहोस्"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"प्रयोगकर्ता फेर्नुहोस्"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"पुलडाउन मेनु"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"यो सत्रमा भएका सबै एपहरू र डेटा मेटाइने छ।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 664af5e..7d21874 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Screenshot opslaan in werkprofiel…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Kan screenshot niet opslaan"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Je moet het apparaat ontgrendelen voordat het screenshot kan worden opgeslagen"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer opnieuw een screenshot te maken"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Kan screenshot niet opslaan"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Casten"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Naamloos apparaat"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Geen apparaten beschikbaar"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wifi niet verbonden"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleurinversie"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurcorrectie"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Snel opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klik op de pijl om de communitytutorial te starten"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index db9e0c5..38039cb 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ୱାର୍କ ପ୍ରୋଫାଇଲରେ ସ୍କ୍ରିନସଟ ସେଭ କରାଯାଉଛି…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ସ୍କ୍ରୀନ୍‍ଶଟ୍ ସେଭ୍ କରିହେବ ନାହିଁ"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ସ୍କ୍ରିନସଟ୍ ସେଭ୍ କରିବା ପୂର୍ବରୁ ଡିଭାଇସକୁ ଅନଲକ୍ କରାଯିବା ଆବଶ୍ୟକ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍‌ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ସ୍କ୍ରିନସଟକୁ ସେଭ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"କାଷ୍ଟିଙ୍ଗ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ନାମହୀନ ଡିଭାଇସ୍‍"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"କୌଣସି ଡିଭାଇସ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ୱାଇ-ଫାଇ ସଂଯୋଜିତ ହୋଇନାହିଁ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ଉଜ୍ଜ୍ୱଳତା"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"କଲର ଇନଭର୍ସନ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ତୀର ବଟନରେ କ୍ଲିକ କରନ୍ତୁ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ୟୁଜର୍‍ ବଦଳାନ୍ତୁ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ପୁଲଡାଉନ ମେନୁ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍‌ ଓ ଡାଟା ଡିଲିଟ୍‌ ହୋଇଯିବ।"</string>
@@ -660,7 +664,7 @@
     <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"ବର୍ତ୍ତମାନର"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"ଫେରନ୍ତୁ"</string>
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ବିଜ୍ଞପ୍ତି"</string>
-    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"କୀ\'ବୋର୍ଡ ସର୍ଟକଟ୍"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"କୀବୋର୍ଡ ସର୍ଟକଟ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"କୀ\'ବୋର୍ଡ୍‍ର ଲେଆଉଟ୍‍କୁ ବଦଳାନ୍ତୁ"</string>
     <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ଟେକ୍ସଟ ଖାଲି କରନ୍ତୁ"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 591c5e7..9011855 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"ਕਾਸਟਿੰਗ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ਬਿਨਾਂ ਨਾਮ ਦਾ ਡੀਵਾਈਸ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ਕੋਈ ਡਿਵਾਈਸਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ਵਾਈ-ਫਾਈ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ਚਮਕ"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"ਰੰਗ ਪਲਟਨਾ"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ਰੰਗ ਸੁਧਾਈ"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਤੀਰ ਬਟਨ \'ਤੇ ਕਲਿੱਕ ਕਰੋ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"ਪੁੱਲਡਾਊਨ ਮੀਨੂ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿਚਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 1951221..9b2b3cf 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Zapisuję zrzut ekranu w profilu służbowym…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nie udało się zapisać zrzutu ekranu"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Przed zapisaniem zrzutu ekranu musisz odblokować urządzenie"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nie można zapisać zrzutu ekranu."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Przesyłam"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Urządzenie bez nazwy"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Brak dostępnych urządzeń"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Brak połączenia z Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jasność"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Odwrócenie kolorów"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcja kolorów"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Szybkie ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknij przycisk strzałki, aby uruchomić samouczek społecznościowy"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 693a3a1..a2b1fdb 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvando captura de tela no perfil de trabalho…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Não foi possível salvar a captura de tela"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Transmitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sem nome"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Não há dispositivos disponíveis"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi não conectado"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregamento rápido • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Clique no botão de seta para iniciar o tutorial compartilhado"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c4f1f67..373cafb 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"A guardar captura de ecrã no perfil de trabalho…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Não foi possível guardar a captura de ecrã"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"É necessário desbloquear o dispositivo para guardar a captura de ecrã"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Experimente voltar a efetuar a captura de ecrã."</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Não é possível guardar a captura de ecrã."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Transmissão"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sem nome"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Sem dispositivos disponíveis"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi não ligado"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção da cor"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar rapidamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Clique no botão de seta para iniciar o tutorial coletivo"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 693a3a1..a2b1fdb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvando captura de tela no perfil de trabalho…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Não foi possível salvar a captura de tela"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Transmitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sem nome"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Não há dispositivos disponíveis"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi não conectado"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregamento rápido • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Clique no botão de seta para iniciar o tutorial compartilhado"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Trocar usuário"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu suspenso"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a942332..1aabc3e 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Se salvează captura în profilul de serviciu…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Nu s-a putut salva captura de ecran"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pentru a salva captura de ecran, trebuie să deblochezi dispozitivul"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Încearcă să faci din nou o captură de ecran"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Nu se poate salva captura de ecran"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Se proiectează"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispozitiv nedenumit"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Niciun dispozitiv disponibil"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Rețeaua Wi-Fi nu este conectată"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminozitate"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversarea culorilor"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corecția culorii"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Dă clic pe butonul săgeată pentru a începe tutorialul pentru comunitate"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Schimbă utilizatorul"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"meniu vertical"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Toate aplicațiile și datele din această sesiune vor fi șterse."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 68601d6..35b4c29 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Сохранение скриншота в рабочем профиле…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не удалось сохранить скриншот"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Чтобы сохранить скриншот, разблокируйте устройство."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Попробуйте сделать скриншот снова."</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Не удалось сохранить скриншот."</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Передача изображения"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Безымянное устройство"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Нет доступных устройств"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Нет подключения к сети Wi-Fi."</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркость"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверсия цветов"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Коррекция цвета"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Быстрая зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Нажмите кнопку со стрелкой, чтобы ознакомиться с руководством"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Сменить пользователя."</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"раскрывающееся меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Все приложения и данные этого профиля будут удалены."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 86cb3c3..f2dd421 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"කාර්යාල පැතිකඩ වෙත තිර රුව සුරකිමින්…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"තිර රුව සුරැකිය නොහැකි විය"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"තිර රුව සුරැකීමට පෙර උපාංගය අගුලු හැරිය යුතුය"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"තිර රුව සුරැකීමට නොහැකිය"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"කාස්ට් කිරීම"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"නම් නොකළ උපාංගය"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"උපාංග නොතිබේ"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi සම්බන්ධ නොවීය"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"දීප්තිමත් බව"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"වර්ණ අපවර්තනය"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"වර්ණ නිවැරදි කිරීම"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"වාර්ගික නිබන්ධනය ආරම්භ කිරීමට ඊතල බොත්තම ක්ලික් කරන්න"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"පරිශීලක මාරුව"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"නිපතන මෙනුව"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 56b9f75..844f30c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ukladá sa snímka obrazovky do pracovného profilu…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímku obrazovky sa nepodarilo uložiť"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred uložením snímky obrazovky je potrebné zariadenie odomknúť"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skúste snímku urobiť znova"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Snímka obrazovky sa nedá uložiť"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Prenáša sa"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nepomenované zariadenie"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nie sú k dispozícii žiadne zariadenia"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Sieť Wi‑Fi nie je pripojená"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzia farieb"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Úprava farieb"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa rýchlo • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Ak chcete spustiť komunitný návod, kliknite na tlačidlo so šípkou"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Prepnutie používateľa"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbaľovacia ponuka"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Všetky aplikácie a údaje v tejto relácii budú odstránené."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b72f750..1eab754 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Shranjevanje posnetka zaslona v delovni profil …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Posnetka zaslona ni bilo mogoče shraniti"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred shranjevanjem posnetka zaslona morate odkleniti napravo"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Poskusite znova ustvariti posnetek zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Posnetka zaslona ni mogoče shraniti"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Predvajanje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Neimenovana naprava"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Na voljo ni nobene naprave"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Povezava Wi-Fi ni vzpostavljena"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svetlost"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija barv"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Popravljanje barv"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hitro polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliknite gumb s puščico, da zaženete vadnico za skupnost"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 92f6f9c..cafd6a0 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pamja e ekranit po ruhet te profili i punës…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Pamja e ekranit nuk mund të ruhej"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pajisja duhet të shkyçet para se të mund të ruhet pamja e ekranit"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Pamja e ekranit nuk mund të ruhet"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Po transmeton"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Pajisje e paemërtuar"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Nuk ofrohet për përdorim asnjë pajisje"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi nuk është lidhur"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ndriçimi"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Anasjellja e ngjyrës"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korrigjimi i ngjyrës"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet shpejt • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Kliko mbi butonin e shigjetës për të filluar udhëzuesin e përbashkët"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyja me tërheqje poshtë"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Të gjitha aplikacionet dhe të dhënat në këtë sesion do të fshihen."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7c0d9be..8c1450a1 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Снимак екрана се чува на пословном профилу…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Чување снимка екрана није успело"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уређај мора да буде откључан да би снимак екрана могао да се сачува"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Пробајте да поново направите снимак екрана"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Чување снимка екрана није успело"</string>
@@ -101,8 +103,8 @@
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
     <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Желите да започнете снимање?"</string>
-    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају док снимате. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
-    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Када снимате апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
+    <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају док снимате. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
+    <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Када снимате апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
     <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Започни снимање"</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Снимај звук"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук уређаја"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Пребацивање"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Неименовани уређај"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Није доступан ниједан уређај"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"WiFi није повезан"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветљеност"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија боја"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција боја"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Кликните на дугме са стрелицом да бисте започели заједнички водич"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Замени корисника"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"падајући мени"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Све апликације и подаци у овој сесији ће бити избрисани."</string>
@@ -418,17 +422,17 @@
     <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Једна апликација"</string>
     <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Делите или снимите апликацију"</string>
     <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Желите да почнете снимање или пребацивање помоћу апликације <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
-    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Када делите, снимате или пребацујете, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
-    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Када делите, снимате или пребацујете апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Када делите, снимате или пребацујете, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
+    <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Када делите, снимате или пребацујете апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
     <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Покрени"</string>
     <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је онемогућила ову опцију"</string>
     <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Желите да започнете пребацивање?"</string>
-    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Када пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
-    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Када пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Када пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
+    <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Када пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
     <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Започни пребацивање"</string>
     <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Желите да почнете да делите?"</string>
-    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Када делите, снимате или пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
-    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Када делите, снимате или пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Када делите, снимате или пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
+    <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Када делите, снимате или пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видеима."</string>
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Покрени"</string>
     <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Дељење се зауставља када мењате апликације"</string>
     <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Дели ову апликацију"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 323ce11f..59bb1f5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sparar skärmbild i jobbprofilen …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmbilden har sparats"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Det gick inte att spara skärmbilden"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skärmbilden kan bara sparas om enheten är upplåst"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Testa att ta en skärmbild igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Det gick inte att spara skärmbilden"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Castar"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Namnlös enhet"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Inga tillgängliga enheter"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Ej ansluten till wifi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ljusstyrka"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Färginvertering"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Färgkorrigering"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas snabbt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Klicka på pilknappen för att börja med gruppguiden"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Byt användare"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rullgardinsmeny"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 304910a..b977dc4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Inahifadhi picha ya skrini kwenye wasifu wa kazini…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Imeshindwa kuhifadhi picha ya skrini"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ni sharti ufungue kifaa kabla ya kuhifadhi picha ya skrini"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Imeshindwa kuhifadhi picha ya skrini"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Inatuma"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Kifaa hakina jina"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Hakuna vifaa vilivyopatikana"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi haijaunganishwa"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ung\'avu"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ugeuzaji rangi"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Usahihishaji wa rangirangi"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Bofya kwenye kitufe cha kishale ili kuanzisha mafunzo ya jumuiya"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Badili mtumiaji"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menyu ya kuvuta chini"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 3ac5e2e..3d05824 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"பணிக் கணக்கில் ஸ்கிரீன்ஷாட் சேமிக்கப்படுகிறது…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"ஸ்கிரீன் ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ஸ்கிரீன்ஷாட் சேமிக்கப்படுவதற்கு முன்பு சாதனம் அன்லாக் செய்யப்பட வேண்டும்"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"அனுப்புகிறது"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"பெயரிடப்படாத சாதனம்"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"சாதனங்கள் இல்லை"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"வைஃபை இணைக்கப்படவில்லை"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ஒளிர்வு"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"கலர் இன்வெர்ஷன்"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"கலர் கரெக்‌ஷன்"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"சமூகப் பயிற்சியைத் தொடங்க அம்புக்குறி பட்டனைக் கிளிக் செய்யுங்கள்"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"பயனரை மாற்று"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"கீழ் இழுக்கும் மெனு"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"இந்த அமர்வின் எல்லா ஆப்ஸும் தரவும் நீக்கப்படும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 0526f95..6d68b63 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"స్క్రీన్‌షాట్‌ను వర్క్ ప్రొఫైల్‌కు సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్‌షాట్ సేవ్ చేయబడింది"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"స్క్రీన్‌షాట్‌ని సేవ్ చేయడం సాధ్యం కాలేదు"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"స్క్రీన్‌షాట్ సేవ్ అవ్వకముందే పరికరం అన్‌లాక్ చేయబడాలి"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"స్క్రీన్‌షాట్ తీయడానికి మళ్లీ ట్రై చేయండి"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడలేదు"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"ప్రసారం చేస్తోంది"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"పేరులేని పరికరం"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"పరికరాలు ఏవీ అందుబాటులో లేవు"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi‑Fi కనెక్ట్ కాలేదు"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ప్రకాశం"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"కలర్ మార్పిడి"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"కలర్ కరెక్షన్"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"కమ్యూనల్ ట్యుటోరియల్‌ను ప్రారంభించడానికి బాణం బటన్‌పై క్లిక్ చేయండి"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"వినియోగదారుని మార్చు"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"పుల్‌డౌన్ మెనూ"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్‌లోని అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8949360..3f5a47e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"กำลังบันทึกภาพหน้าจอไปยังโปรไฟล์งาน…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"บันทึกภาพหน้าจอไม่ได้"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ต้องปลดล็อกอุปกรณ์ก่อนจึงจะบันทึกภาพหน้าจอได้"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ลองบันทึกภาพหน้าจออีกครั้ง"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"บันทึกภาพหน้าจอไม่ได้"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"กำลังส่ง"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"อุปกรณ์ที่ไม่มีชื่อ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"ไม่มีอุปกรณ์ที่สามารถใช้ได้"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ไม่ได้เชื่อมต่อ Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ความสว่าง"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"การกลับสี"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"การแก้สี"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"คลิกปุ่มลูกศรเพื่อเริ่มบทแนะนำส่วนกลาง"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"สลับผู้ใช้"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"เมนูแบบเลื่อนลง"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e5c11df..3fac637 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sine-save ang screenshot sa profile sa trabaho…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Hindi ma-save ang screenshot"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Dapat naka-unlock ang device bago ma-save ang screenshot"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Subukang kumuhang muli ng screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Hindi ma-save ang screenshot"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Nagka-cast"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Walang pangalang device"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Walang available na mga device"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Hindi nakakonekta sa Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Pag-invert ng kulay"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pagtatama ng kulay"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"I-click ang arrow button para simulan ang communal na tutorial"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3552d92..ca357b41 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ekran görüntüsü iş profiline kaydediliyor…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekran görüntüsü kaydedilemedi"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ekran görüntüsünün kaydedilebilmesi için cihazın kilidi açık olmalıdır"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tekrar ekran görüntüsü almayı deneyin"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ekran görüntüsü kaydedilemiyor"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Yayınlanıyor"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Adsız cihaz"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Kullanılabilir cihaz yok"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Kablosuz ağ bağlı değil"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaklık"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rengi ters çevirme"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Renk düzeltme"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Ortak eğitimi başlatmak için ok düğmesini tıklayın"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Kullanıcı değiştirme"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"açılır menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 2e6aea9..6078e31 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Зберігання знімка екрана в робочому профілі…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Не вдалося зберегти знімок екрана"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Щоб зберегти знімок екрана, розблокуйте пристрій"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Спробуйте зробити знімок екрана ще раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Не вдалося зберегти знімок екрана"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Трансляція"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Пристрій без назви"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Немає пристроїв"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi не під’єднано"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яскравість"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія кольорів"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекція кольору"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Натисніть кнопку зі стрілкою, щоб відкрити спільний навчальний посібник"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Змінити користувача"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"спадне меню"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усі додатки й дані з цього сеансу буде видалено."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 2e2fc41..5cf763f 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"اسکرین شاٹ دفتری پروفائل میں محفوظ کیا جا رہا ہے…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکا"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"اسکرین شاٹ محفوظ کرنے سے پہلے آلے کو غیر مقفل کرنا ضروری ہے"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"کاسٹنگ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"بغیر نام والا آلہ"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"کوئی آلات دستیاب نہیں ہیں"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"‏Wi-Fi سے منسلک نہیں ہے"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"چمکیلا پن"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"رنگوں کی تقلیب"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"رنگ کی اصلاح"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"کمیونل ٹیوٹوریل شروع کرنے کے لیے تیر کے نشان والے بٹن پر کلک کریں"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"صارف سوئچ کریں"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"پل ڈاؤن مینیو"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"اس سیشن میں موجود سبھی ایپس اور ڈیٹا کو حذف کر دیا جائے گا۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a8654d5..412dd8a 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -20,8 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4811759950673118541">"Tizim interfeysi"</string>
-    <string name="battery_low_title" msgid="5319680173344341779">"Quvvat tejash funksiyasi yoqilsinmi?"</string>
-    <string name="battery_low_description" msgid="3282977755476423966">"<xliff:g id="PERCENTAGE">%s</xliff:g> batareya quvvati qoldi. Quvvat tejash funksiyasi Tungi mavzuni yoqadi va fondagi faollikni cheklaydi. Buning natijasida bildirishnomalar kechikishi mumkin."</string>
+    <string name="battery_low_title" msgid="5319680173344341779">"Quvvat tejash yoqilsinmi?"</string>
+    <string name="battery_low_description" msgid="3282977755476423966">"Batareya quvvati <xliff:g id="PERCENTAGE">%s</xliff:g> qoldi. Quvvat tejash funksiyasi Tungi mavzuni yoqadi va fondagi faollikni cheklaydi. Buning natijasida bildirishnomalar kechikishi mumkin."</string>
     <string name="battery_low_intro" msgid="5148725009653088790">"Quvvat tejash funksiyasi Tungi mavzuni yoqadi va fondagi faollikni cheklaydi. Buning natijasida bildirishnomalar kechikishi mumkin."</string>
     <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi"</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"USB orqali quvvatlash imkonsiz"</string>
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Skrinshot ish profiliga saqlanmoqda…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinshot saqlanmadi"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinshotni saqlashdan oldin qurilma qulflanmagan boʻlishi lozim"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Qayta skrinshot olib ko‘ring"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Skrinshot saqlanmadi"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Translatsiya qilinmoqda"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Nomsiz qurilma"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Qurilmalar topilmadi"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi tarmoqqa ulanmagan"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Yorqinlik"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ranglarni akslantirish"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ranglarni tuzatish"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Tez quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Qoʻllanma bilan tanishish uchun strelka tugmasini bosing"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Foydalanuvchini almashtirish"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"tortib tushiriladigan menyu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ushbu seansdagi barcha ilovalar va ma’lumotlar o‘chirib tashlanadi."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5443745..45dfc45 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Đang lưu ảnh chụp màn hình vào hồ sơ công việc…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Không thể lưu ảnh chụp màn hình"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Bạn phải mở khóa thiết bị để chúng tôi có thể lưu ảnh chụp màn hình"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Hãy thử chụp lại màn hình"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Không thể lưu ảnh chụp màn hình"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Đang truyền"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Thiết bị không có tên"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Không có thiết bị nào"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Chưa kết nối với Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Độ sáng"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Đảo màu"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Chỉnh màu"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Nhấp vào nút mũi tên để bắt đầu xem hướng dẫn chung"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Chuyển đổi người dùng"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"trình đơn kéo xuống"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tất cả ứng dụng và dữ liệu trong phiên này sẽ bị xóa."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 44c163b..17a66787 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在将屏幕截图保存到工作资料…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"无法保存屏幕截图"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必须先解锁设备,然后才能保存屏幕截图"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"请再次尝试截屏"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"无法保存屏幕截图"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"正在投放"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"未命名设备"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"没有可用设备"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"未连接到 WLAN 网络"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"颜色反转"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"点击箭头按钮,即可启动公共教程"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切换用户"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉菜单"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f45b2fe..48fbf7c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在將螢幕截圖儲存至工作設定檔…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕擷取畫面"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再嘗試拍攝螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"無法儲存螢幕截圖"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"正在放送"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"未命名的裝置"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"沒有可用裝置"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"未連線至 Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"按一下箭咀鍵,即可開始共用教學課程"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 5a5bb9d..55d4cb6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在將螢幕截圖儲存到工作資料夾…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕截圖"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再次嘗試拍攝螢幕截圖"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"無法儲存螢幕截圖"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"投放"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"未命名的裝置"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"沒有可用裝置"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"未連線至 Wi-Fi"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"點選箭頭按鈕,即可開始通用教學課程"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"切換使用者"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"下拉式選單"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會遭到刪除。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8b6bfae..b883b9a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -76,6 +76,8 @@
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ilondoloza isithombe-skrini kuphrofayela yomsebenzi…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string>
     <string name="screenshot_failed_title" msgid="3259148215671936891">"Ayikwazanga ukulondoloza isithombe-skrini"</string>
+    <!-- no translation found for screenshot_failed_external_display_indication (6555673132061101936) -->
+    <skip />
     <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Idivayisi kufanele ivulwe ngaphambi kokuthi isithombe-skrini singalondolozwa"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zama ukuthatha isithombe-skrini futhi"</string>
     <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Ayikwazi ukulondoloza isithombe-skrini"</string>
@@ -280,7 +282,8 @@
     <string name="quick_settings_casting" msgid="1435880708719268055">"Ukusakaza"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Idivayisi engenalo igama"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="2846282280014617785">"Ayikho idivayisi etholakalayo"</string>
-    <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"I-Wi-Fi ayixhunyiwe"</string>
+    <!-- no translation found for quick_settings_cast_no_network (3863016850468559522) -->
+    <skip />
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ukugqama"</string>
     <string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ukuguqulwa kombala"</string>
     <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ukulungiswa kombala"</string>
@@ -395,6 +398,7 @@
     <string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja ngokushesha • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+    <string name="communal_tutorial_indicator_text" msgid="700342473477865107">"Chofoza inkinobho yomcibisholo ukuze uqalise isifundo somphakathi"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Shintsha umsebenzisi"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"imenyu yokudonsela phansi"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wonke ama-app nedatha kulesi sikhathi azosuswa."</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt
similarity index 77%
copy from packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
copy to packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt
index 0aa6b0b..9b7cd70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Tracing.kt
@@ -13,10 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.systemui.dagger.qualifiers
 
-package com.android.systemui.qs.tiles.base.interactor
+import javax.inject.Qualifier
 
-data class QSTileDataRequest(
-    val userId: Int,
-    val trigger: StateUpdateTrigger,
-)
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class Tracing
diff --git a/packages/SystemUI/shared/src/com/android/systemui/util/TraceUtils.kt b/packages/SystemUI/shared/src/com/android/systemui/util/TraceUtils.kt
index 7b2e1af..e459034 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/util/TraceUtils.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/util/TraceUtils.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,13 +18,25 @@
 
 import android.os.Trace
 import android.os.TraceNameSupplier
+import android.util.Log
+import com.android.systemui.util.tracing.TraceContextElement
+import com.android.systemui.util.tracing.TraceData
+import com.android.systemui.util.tracing.TraceData.Companion.FIRST_VALID_SPAN
+import com.android.systemui.util.tracing.TraceData.Companion.INVALID_SPAN
+import com.android.systemui.util.tracing.threadLocalTrace
 import java.util.concurrent.atomic.AtomicInteger
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.coroutines.coroutineContext
+import kotlin.random.Random
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
 
 /**
  * Run a block within a [Trace] section. Calls [Trace.beginSection] before and [Trace.endSection]
@@ -44,6 +56,10 @@
 
 class TraceUtils {
     companion object {
+        const val TAG = "TraceUtils"
+        private const val DEBUG_COROUTINE_TRACING = false
+        const val DEFAULT_TRACK_NAME = "AsyncTraces"
+
         inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable {
             return Runnable { traceSection(tag) { block() } }
         }
@@ -73,7 +89,7 @@
          * under a single track.
          */
         inline fun <T> traceAsync(method: String, block: () -> T): T =
-            traceAsync("AsyncTraces", method, block)
+            traceAsync(DEFAULT_TRACK_NAME, method, block)
 
         /**
          * Creates an async slice in a track with [trackName] while [block] runs.
@@ -93,16 +109,313 @@
         }
 
         /**
-         * Convenience method to avoid one indentation level when we want to add a trace when
-         * launching a coroutine
+         * Convenience function for calling [CoroutineScope.launch] with [traceCoroutine] enable
+         * tracing.
+         *
+         * @see traceCoroutine
          */
-        fun <T> CoroutineScope.tracedAsync(
-            method: String,
+        inline fun CoroutineScope.launch(
+            crossinline spanName: () -> String,
             context: CoroutineContext = EmptyCoroutineContext,
-            start: CoroutineStart = CoroutineStart.DEFAULT,
-            block: suspend () -> T
-        ): Deferred<T> {
-            return async(context, start) { traceAsync(method) { block() } }
+            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
+            crossinline block: suspend CoroutineScope.() -> Unit
+        ): Job = launch(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [CoroutineScope.launch] with [traceCoroutine] enable
+         * tracing.
+         *
+         * @see traceCoroutine
+         */
+        inline fun CoroutineScope.launch(
+            spanName: String,
+            context: CoroutineContext = EmptyCoroutineContext,
+            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
+            crossinline block: suspend CoroutineScope.() -> Unit
+        ): Job = launch(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [CoroutineScope.async] with [traceCoroutine] enable
+         * tracing
+         *
+         * @see traceCoroutine
+         */
+        inline fun <T> CoroutineScope.async(
+            crossinline spanName: () -> String,
+            context: CoroutineContext = EmptyCoroutineContext,
+            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
+            crossinline block: suspend CoroutineScope.() -> T
+        ): Deferred<T> = async(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [CoroutineScope.async] with [traceCoroutine] enable
+         * tracing.
+         *
+         * @see traceCoroutine
+         */
+        inline fun <T> CoroutineScope.async(
+            spanName: String,
+            context: CoroutineContext = EmptyCoroutineContext,
+            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
+            crossinline block: suspend CoroutineScope.() -> T
+        ): Deferred<T> = async(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [runBlocking] with [traceCoroutine] to enable tracing.
+         *
+         * @see traceCoroutine
+         */
+        inline fun <T> runBlocking(
+            crossinline spanName: () -> String,
+            context: CoroutineContext,
+            crossinline block: suspend () -> T
+        ): T = runBlocking(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [runBlocking] with [traceCoroutine] to enable tracing.
+         *
+         * @see traceCoroutine
+         */
+        inline fun <T> runBlocking(
+            spanName: String,
+            context: CoroutineContext,
+            crossinline block: suspend CoroutineScope.() -> T
+        ): T = runBlocking(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [withContext] with [traceCoroutine] to enable tracing.
+         *
+         * @see traceCoroutine
+         */
+        suspend inline fun <T> withContext(
+            spanName: String,
+            context: CoroutineContext,
+            crossinline block: suspend CoroutineScope.() -> T
+        ): T = withContext(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * Convenience function for calling [withContext] with [traceCoroutine] to enable tracing.
+         *
+         * @see traceCoroutine
+         */
+        suspend inline fun <T> withContext(
+            crossinline spanName: () -> String,
+            context: CoroutineContext,
+            crossinline block: suspend CoroutineScope.() -> T
+        ): T = withContext(context) { traceCoroutine(spanName) { block() } }
+
+        /**
+         * A hacky way to propagate the value of the COROUTINE_TRACING flag for static usage in this
+         * file. It should only every be set to true during startup. Once true, it cannot be set to
+         * false again.
+         */
+        var coroutineTracingIsEnabled = false
+            set(v) {
+                if (v) field = true
+            }
+
+        /**
+         * Traces a section of work of a `suspend` [block]. The trace sections will appear on the
+         * thread that is currently executing the [block] of work. If the [block] is suspended, all
+         * trace sections added using this API will end until the [block] is resumed, which could
+         * happen either on this thread or on another thread. If a child coroutine is started, it
+         * will inherit the trace sections of its parent. The child will continue to print these
+         * trace sections whether or not the parent coroutine is still running them.
+         *
+         * The current [CoroutineContext] must have a [TraceContextElement] for this API to work.
+         * Otherwise, the trace sections will be dropped.
+         *
+         * For example, in the following trace, Thread #1 ran some work, suspended, then continued
+         * working on Thread #2. Meanwhile, Thread #2 created a new child coroutine which inherited
+         * its trace sections. Then, the original coroutine resumed on Thread #1 before ending.
+         * Meanwhile Thread #3 is still printing trace sections from its parent because they were
+         * copied when it was created. There is no way for the parent to communicate to the child
+         * that it marked these slices as completed. While this might seem counterintuitive, it
+         * allows us to pinpoint the origin of the child coroutine's work.
+         *
+         * ```
+         * Thread #1 | [==== Slice A ====]                        [==== Slice A ====]
+         *           |       [==== B ====]                        [=== B ===]
+         * --------------------------------------------------------------------------------------
+         * Thread #2 |                    [====== Slice A ======]
+         *           |                    [========= B =========]
+         *           |                        [===== C ======]
+         * --------------------------------------------------------------------------------------
+         * Thread #3 |                            [== Slice A ==]                [== Slice A ==]
+         *           |                            [===== B =====]                [===== B =====]
+         *           |                            [===== C =====]                [===== C =====]
+         *           |                                                               [=== D ===]
+         * ```
+         *
+         * @param name The name of the code section to appear in the trace
+         * @see endSlice
+         * @see traceCoroutine
+         */
+        @OptIn(ExperimentalCoroutinesApi::class)
+        suspend inline fun <T> traceCoroutine(
+            spanName: Lazy<String>,
+            crossinline block: suspend () -> T
+        ): T {
+            // For coroutine tracing to work, trace spans must be added and removed even when
+            // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the
+            // coroutine resumes when tracing is active, we won't know its name.
+            val tracer = getTraceData(spanName)
+            val coroutineSpanCookie = tracer?.beginSpan(spanName.value) ?: INVALID_SPAN
+
+            // For now, also trace to "AsyncTraces". This will allow us to verify the correctness
+            // of the COROUTINE_TRACING feature flag.
+            val asyncTraceCookie =
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_APP))
+                    Random.nextInt(FIRST_VALID_SPAN, Int.MAX_VALUE)
+                else INVALID_SPAN
+            if (asyncTraceCookie != INVALID_SPAN) {
+                Trace.asyncTraceForTrackBegin(
+                    Trace.TRACE_TAG_APP,
+                    DEFAULT_TRACK_NAME,
+                    spanName.value,
+                    asyncTraceCookie
+                )
+            }
+            try {
+                return block()
+            } finally {
+                if (asyncTraceCookie != INVALID_SPAN) {
+                    Trace.asyncTraceForTrackEnd(
+                        Trace.TRACE_TAG_APP,
+                        DEFAULT_TRACK_NAME,
+                        asyncTraceCookie
+                    )
+                }
+                tracer?.endSpan(coroutineSpanCookie)
+            }
+        }
+
+        @OptIn(ExperimentalCoroutinesApi::class)
+        suspend fun getTraceData(spanName: Lazy<String>): TraceData? {
+            if (!coroutineTracingIsEnabled) {
+                logVerbose("Experimental flag COROUTINE_TRACING is off", spanName)
+            } else if (coroutineContext[TraceContextElement] == null) {
+                logVerbose("Current CoroutineContext is missing TraceContextElement", spanName)
+            } else {
+                return threadLocalTrace.get().also {
+                    if (it == null) logVerbose("ThreadLocal TraceData is null", spanName)
+                }
+            }
+            return null
+        }
+
+        private fun logVerbose(logMessage: String, spanName: Lazy<String>) {
+            if (DEBUG_COROUTINE_TRACING && Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "$logMessage. Dropping trace section: \"${spanName.value}\"")
+            }
+        }
+
+        /** @see traceCoroutine */
+        suspend inline fun <T> traceCoroutine(
+            spanName: String,
+            crossinline block: suspend () -> T
+        ): T = traceCoroutine(lazyOf(spanName)) { block() }
+
+        /** @see traceCoroutine */
+        suspend inline fun <T> traceCoroutine(
+            crossinline spanName: () -> String,
+            crossinline block: suspend () -> T
+        ): T = traceCoroutine(lazy(LazyThreadSafetyMode.PUBLICATION) { spanName() }) { block() }
+
+        /**
+         * Writes a trace message to indicate that a given section of code has begun running __on
+         * the current thread__. This must be followed by a corresponding call to [endSlice] in a
+         * reasonably short amount of time __on the same thread__ (i.e. _before_ the thread becomes
+         * idle again and starts running other, unrelated work).
+         *
+         * Calls to [beginSlice] and [endSlice] may be nested, and they will render in Perfetto as
+         * follows:
+         * ```
+         * Thread #1 | [==========================]
+         *           |       [==============]
+         *           |           [====]
+         * ```
+         *
+         * This function is provided for convenience to wrap a call to [Trace.traceBegin], which is
+         * more verbose to call than [Trace.beginSection], but has the added benefit of not throwing
+         * an [IllegalArgumentException] if the provided string is longer than 127 characters. We
+         * use the term "slice" instead of "section" to be consistent with Perfetto.
+         *
+         * # Avoiding malformed traces
+         *
+         * Improper usage of this API will lead to malformed traces with long slices that sometimes
+         * never end. This will look like the following:
+         * ```
+         * Thread #1 | [===================================================================== ...
+         *           |       [==============]         [====================================== ...
+         *           |           [=======]              [======]       [===================== ...
+         *           |                                                       [=======]
+         * ```
+         *
+         * To avoid this, [beginSlice] and [endSlice] should never be called from `suspend` blocks
+         * (instead, use [traceCoroutine] for tracing suspending functions). While it would be
+         * technically okay to call from a suspending function if that function were to only wrap
+         * non-suspending blocks with [beginSlice] and [endSlice], doing so is risky because suspend
+         * calls could be mistakenly added to that block as the code is refactored.
+         *
+         * Additionally, it is _not_ okay to call [beginSlice] when registering a callback and match
+         * it with a call to [endSlice] inside that callback, even if the callback runs on the same
+         * thread. Doing so would cause malformed traces because the [beginSlice] wasn't closed
+         * before the thread became idle and started running unrelated work.
+         *
+         * @param sliceName The name of the code section to appear in the trace
+         * @see endSlice
+         * @see traceCoroutine
+         */
+        fun beginSlice(sliceName: String) {
+            Trace.traceBegin(Trace.TRACE_TAG_APP, sliceName)
+        }
+
+        /**
+         * Writes a trace message to indicate that a given section of code has ended. This call must
+         * be preceded by a corresponding call to [beginSlice]. See [beginSlice] for important
+         * information regarding usage.
+         *
+         * @see beginSlice
+         * @see traceCoroutine
+         */
+        fun endSlice() {
+            Trace.traceEnd(Trace.TRACE_TAG_APP)
+        }
+
+        /**
+         * Writes a trace message indicating that an instant event occurred on the current thread.
+         * Unlike slices, instant events have no duration and do not need to be matched with another
+         * call. Perfetto will display instant events using an arrow pointing to the timestamp they
+         * occurred:
+         * ```
+         * Thread #1 | [==============]               [======]
+         *           |     [====]                        ^
+         *           |        ^
+         * ```
+         *
+         * @param eventName The name of the event to appear in the trace.
+         */
+        fun instant(eventName: String) {
+            Trace.instant(Trace.TRACE_TAG_APP, eventName)
+        }
+
+        /**
+         * Writes a trace message indicating that an instant event occurred on the given track.
+         * Unlike slices, instant events have no duration and do not need to be matched with another
+         * call. Perfetto will display instant events using an arrow pointing to the timestamp they
+         * occurred:
+         * ```
+         * Async  | [==============]               [======]
+         *  Track |     [====]                        ^
+         *   Name |        ^
+         * ```
+         *
+         * @param trackName The track where the event should appear in the trace.
+         * @param eventName The name of the event to appear in the trace.
+         */
+        fun instantForTrack(trackName: String, eventName: String) {
+            Trace.instantForTrack(Trace.TRACE_TAG_APP, trackName, eventName)
         }
     }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceContextElement.kt b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceContextElement.kt
new file mode 100644
index 0000000..4d8c545
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceContextElement.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.tracing
+
+import com.android.systemui.util.TraceUtils.Companion.instant
+import com.android.systemui.util.TraceUtils.Companion.traceCoroutine
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CopyableThreadContextElement
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+/**
+ * Used for safely persisting [TraceData] state when coroutines are suspended and resumed.
+ *
+ * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
+ * because [traceCoroutine] is a Public-API inline function.
+ *
+ * @see traceCoroutine
+ */
+@OptIn(DelicateCoroutinesApi::class)
+@ExperimentalCoroutinesApi
+class TraceContextElement(private val traceData: TraceData = TraceData()) :
+    CopyableThreadContextElement<TraceData?> {
+
+    companion object Key : CoroutineContext.Key<TraceContextElement>
+
+    override val key: CoroutineContext.Key<TraceContextElement> = Key
+
+    @OptIn(ExperimentalStdlibApi::class)
+    override fun updateThreadContext(context: CoroutineContext): TraceData? {
+        val oldState = threadLocalTrace.get()
+        oldState?.endAllOnThread()
+        threadLocalTrace.set(traceData)
+        instant("resuming ${context[CoroutineDispatcher]}")
+        traceData.beginAllOnThread()
+        return oldState
+    }
+
+    @OptIn(ExperimentalStdlibApi::class)
+    override fun restoreThreadContext(context: CoroutineContext, oldState: TraceData?) {
+        instant("suspending ${context[CoroutineDispatcher]}")
+        traceData.endAllOnThread()
+        threadLocalTrace.set(oldState)
+        oldState?.beginAllOnThread()
+    }
+
+    override fun copyForChild(): CopyableThreadContextElement<TraceData?> {
+        return TraceContextElement(traceData.copy())
+    }
+
+    override fun mergeForChild(overwritingElement: CoroutineContext.Element): CoroutineContext {
+        return TraceContextElement(traceData.copy())
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceData.kt b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceData.kt
new file mode 100644
index 0000000..0ae58fc
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceData.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.tracing
+
+import android.os.Build
+import android.util.Log
+import com.android.systemui.util.TraceUtils.Companion.beginSlice
+import com.android.systemui.util.TraceUtils.Companion.endSlice
+import com.android.systemui.util.TraceUtils.Companion.traceCoroutine
+import kotlin.random.Random
+
+/**
+ * Used for giving each thread a unique [TraceData] for thread-local storage. `null` by default.
+ * [threadLocalTrace] can only be used when it is paired with a [TraceContextElement].
+ *
+ * This ThreadLocal will be `null` if either 1) we aren't in a coroutine, or 2) the coroutine we are
+ * in does not have a [TraceContextElement].
+ *
+ * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
+ * because [traceCoroutine] is a Public-API inline function.
+ *
+ * @see traceCoroutine
+ */
+val threadLocalTrace = ThreadLocal<TraceData?>()
+
+/**
+ * Used for storing trace sections so that they can be added and removed from the currently running
+ * thread when the coroutine is suspended and resumed.
+ *
+ * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
+ * because [traceCoroutine] is a Public-API inline function.
+ *
+ * @see traceCoroutine
+ */
+class TraceData {
+    private var slices = mutableListOf<TraceSection>()
+
+    /** Adds current trace slices back to the current thread. Called when coroutine is resumed. */
+    fun beginAllOnThread() {
+        slices.forEach { beginSlice(it.name) }
+    }
+
+    /**
+     * Removes all current trace slices from the current thread. Called when coroutine is suspended.
+     */
+    fun endAllOnThread() {
+        for (i in 0..slices.size) {
+            endSlice()
+        }
+    }
+
+    /**
+     * Creates a new trace section with a unique ID and adds it to the current trace data. The slice
+     * will also be added to the current thread immediately. This slice will not propagate to parent
+     * coroutines, or to child coroutines that have already started. The unique ID is used to verify
+     * that the [endSpan] is corresponds to a [beginSpan].
+     */
+    fun beginSpan(name: String): Int {
+        val newSlice = TraceSection(name, Random.nextInt(FIRST_VALID_SPAN, Int.MAX_VALUE))
+        slices.add(newSlice)
+        beginSlice(name)
+        return newSlice.id
+    }
+
+    /**
+     * Used by [TraceContextElement] when launching a child coroutine so that the child coroutine's
+     * state is isolated from the parent.
+     */
+    fun copy(): TraceData {
+        return TraceData().also { it.slices.addAll(slices) }
+    }
+
+    /**
+     * Ends the trace section and validates it corresponds with an earlier call to [beginSpan]. The
+     * trace slice will immediately be removed from the current thread. This information will not
+     * propagate to parent coroutines, or to child coroutines that have already started.
+     */
+    fun endSpan(id: Int) {
+        val v = slices.removeLast()
+        if (v.id != id) {
+            if (STRICT_MODE) {
+                throw IllegalArgumentException(errorMsg)
+            } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, errorMsg)
+            }
+        }
+        endSlice()
+    }
+
+    companion object {
+        private const val TAG = "TraceData"
+        const val INVALID_SPAN = -1
+        const val FIRST_VALID_SPAN = 1
+
+        /**
+         * If true, throw an exception instead of printing a warning when trace sections beginnings
+         * and ends are mismatched.
+         */
+        private val STRICT_MODE = Build.IS_ENG
+
+        private const val errorMsg =
+            "Mismatched trace section. This likely means you are accessing the trace local " +
+                "storage (threadLocalTrace) without a corresponding CopyableThreadContextElement." +
+                " This could happen if you are using a global dispatcher like Dispatchers.IO." +
+                " To fix this, use one of the coroutine contexts provided by the dagger scope " +
+                "(e.g. \"@Main CoroutineContext\")."
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceSection.kt b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceSection.kt
new file mode 100644
index 0000000..b70c497
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/util/tracing/TraceSection.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.tracing
+
+import com.android.systemui.util.TraceUtils.Companion.traceCoroutine
+
+/**
+ * Represents a section of code executing in a coroutine. This can be split up into multiple slices
+ * on different threads as the coroutine is suspended and resumed.
+ *
+ * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
+ * because [traceCoroutine] is a Public-API inline function.
+ *
+ * @param name the name of the slice to appear on the current thread's track.
+ * @param id used for matching the beginning and end of trace sections and validating correctness
+ * @see traceCoroutine
+ */
+data class TraceSection(
+    val name: String,
+    val 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 fae9fec..a263361 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -39,6 +39,12 @@
     @IntoSet
     abstract fun bindsScreenIdleCondition(impl: ScreenIdleCondition): ConditionalRestarter.Condition
 
+    @Binds
+    @IntoSet
+    abstract fun bindsNotOccludedCondition(
+        impl: NotOccludedCondition
+    ): ConditionalRestarter.Condition
+
     @Module
     companion object {
         @JvmStatic
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 7aacb4e..9684d5e 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -39,6 +39,12 @@
     @IntoSet
     abstract fun bindsPluggedInCondition(impl: PluggedInCondition): ConditionalRestarter.Condition
 
+    @Binds
+    @IntoSet
+    abstract fun bindsNotOccludedCondition(
+        impl: NotOccludedCondition
+    ): ConditionalRestarter.Condition
+
     @Module
     companion object {
         @JvmStatic
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 453a7a6..8ea867b 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -28,6 +28,8 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
 import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.util.TraceUtils.Companion.async
+import com.android.systemui.util.TraceUtils.Companion.withContext
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
 import kotlin.math.max
@@ -263,7 +265,7 @@
      *   not being throttled.
      */
     private suspend fun refreshThrottling(): Long {
-        return withContext(backgroundDispatcher) {
+        return withContext("$TAG#refreshThrottling", backgroundDispatcher) {
             val failedAttemptCount = async { repository.getFailedAuthenticationAttemptCount() }
             val deadline = async { repository.getThrottlingEndTimestamp() }
             val remainingMs = max(0, deadline.await() - clock.elapsedRealtime())
@@ -311,6 +313,10 @@
                 DomainLayerAuthenticationMethodModel.Pattern
         }
     }
+
+    companion object {
+        const val TAG = "AuthenticationInteractor"
+    }
 }
 
 /** Result of a user authentication attempt. */
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
new file mode 100644
index 0000000..8d5b84f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+package com.android.systemui.common.ui
+
+import android.content.Context
+import androidx.annotation.AttrRes
+import androidx.annotation.ColorInt
+import androidx.annotation.DimenRes
+import com.android.settingslib.Utils
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
+import com.android.systemui.statusbar.policy.onThemeChanged
+import com.android.systemui.util.kotlin.emitOnStart
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** Configuration-aware-state-tracking utilities. */
+class ConfigurationState
+@Inject
+constructor(
+    private val configurationController: ConfigurationController,
+    @Application private val context: Context,
+) {
+    /**
+     * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+     * configuration.
+     *
+     * @see android.content.res.Resources.getDimensionPixelSize
+     */
+    fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int> {
+        return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
+            context.resources.getDimensionPixelSize(id)
+        }
+    }
+
+    /**
+     * Returns a [Flow] that emits a color that is kept in sync with the device theme.
+     *
+     * @see Utils.getColorAttrDefaultColor
+     */
+    fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int> {
+        return configurationController.onThemeChanged.emitOnStart().map {
+            Utils.getColorAttrDefaultColor(context, id, defaultValue)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/data/CommonUiDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/common/ui/data/CommonUiDataLayerModule.kt
new file mode 100644
index 0000000..b0e6931
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/data/CommonUiDataLayerModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.common.ui.data
+
+import com.android.systemui.common.ui.data.repository.ConfigurationRepositoryModule
+import dagger.Module
+
+@Module(includes = [ConfigurationRepositoryModule::class]) object CommonUiDataLayerModule
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt b/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
index b8de8d8..e449274 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/ConfigurationRepository.kt
@@ -13,18 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
+@file:OptIn(ExperimentalCoroutinesApi::class)
 
 package com.android.systemui.common.ui.data.repository
 
 import android.content.Context
 import android.content.res.Configuration
 import android.view.DisplayInfo
+import androidx.annotation.DimenRes
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.wrapper.DisplayUtilsWrapper
+import dagger.Binds
+import dagger.Module
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -48,7 +52,6 @@
     fun getDimensionPixelSize(id: Int): Int
 }
 
-@ExperimentalCoroutinesApi
 @SysUISingleton
 class ConfigurationRepositoryImpl
 @Inject
@@ -119,7 +122,12 @@
         return 1f
     }
 
-    override fun getDimensionPixelSize(id: Int): Int {
+    override fun getDimensionPixelSize(@DimenRes id: Int): Int {
         return context.resources.getDimensionPixelSize(id)
     }
 }
+
+@Module
+interface ConfigurationRepositoryModule {
+    @Binds fun bindImpl(impl: ConfigurationRepositoryImpl): ConfigurationRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
index 53b6879..485e512 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.communal.data.repository
 
+import com.android.systemui.FeatureFlags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -15,10 +16,11 @@
 class CommunalRepositoryImpl
 @Inject
 constructor(
-    private val featureFlags: FeatureFlagsClassic,
+    private val featureFlags: FeatureFlags,
+    private val featureFlagsClassic: FeatureFlagsClassic,
 ) : CommunalRepository {
     override val isCommunalEnabled: Boolean
         get() =
-            featureFlags.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) &&
-                featureFlags.isEnabled(Flags.COMMUNAL_HUB)
+            featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) &&
+                featureFlags.communalHub()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index f0d7592..04b2852d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -41,7 +41,7 @@
 import com.android.systemui.bouncer.ui.BouncerViewModule;
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule;
-import com.android.systemui.common.ui.data.repository.CommonRepositoryModule;
+import com.android.systemui.common.ui.data.CommonUiDataLayerModule;
 import com.android.systemui.communal.dagger.CommunalModule;
 import com.android.systemui.complication.dagger.ComplicationComponent;
 import com.android.systemui.controls.dagger.ControlsModule;
@@ -170,7 +170,7 @@
         BouncerViewModule.class,
         ClipboardOverlayModule.class,
         ClockRegistryModule.class,
-        CommonRepositoryModule.class,
+        CommonUiDataLayerModule.class,
         CommunalModule.class,
         ConnectivityModule.class,
         ControlsModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index 4f16685..3e2ecee 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -47,6 +47,8 @@
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 
 /** Provides a [Flow] of [Display] as returned by [DisplayManager]. */
@@ -54,10 +56,7 @@
     /** Display change event indicating a change to the given displayId has occurred. */
     val displayChangeEvent: Flow<Int>
 
-    /**
-     * Provides a nullable set of displays. Updates when new displays have been added or removed but
-     * not when a display's info has changed.
-     */
+    /** Provides the current set of displays. */
     val displays: Flow<Set<Display>>
 
     /**
@@ -112,10 +111,6 @@
                             trySend(DisplayEvent.Changed(displayId))
                         }
                     }
-                // Triggers an initial event when subscribed. This is needed to avoid getDisplays to
-                // be called when this class is constructed, but only when someone subscribes to
-                // this flow.
-                trySend(DisplayEvent.Changed(Display.DEFAULT_DISPLAY))
                 displayManager.registerDisplayListener(
                     callback,
                     backgroundHandler,
@@ -125,6 +120,7 @@
                 )
                 awaitClose { displayManager.unregisterDisplayListener(callback) }
             }
+            .onStart { emit(DisplayEvent.Changed(Display.DEFAULT_DISPLAY)) }
             .flowOn(backgroundCoroutineDispatcher)
 
     override val displayChangeEvent: Flow<Int> =
@@ -134,13 +130,9 @@
         allDisplayEvents
             .map { getDisplays() }
             .flowOn(backgroundCoroutineDispatcher)
-            .stateIn(
-                applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                // To avoid getting displays on this object construction, they are get after the
-                // first event. allDisplayEvents emits a changed event when we subscribe to it.
-                initialValue = emptySet()
-            )
+            .shareIn(applicationScope, started = SharingStarted.WhileSubscribed(), replay = 1)
+
+    override val displays: Flow<Set<Display>> = enabledDisplays
 
     private fun getDisplays(): Set<Display> =
         traceSection("DisplayRepository#getDisplays()") {
@@ -148,8 +140,6 @@
         }
 
     /** Propagate to the listeners only enabled displays */
-    override val displays: Flow<Set<Display>> = enabledDisplays
-
     private val enabledDisplayIds: Flow<Set<Int>> =
         enabledDisplays
             .map { enabledDisplaysSet -> enabledDisplaysSet.map { it.displayId }.toSet() }
@@ -251,6 +241,7 @@
                 val id = pendingDisplayIds.maxOrNull() ?: return@map null
                 object : DisplayRepository.PendingDisplay {
                     override val id = id
+
                     override suspend fun enable() {
                         traceSection("DisplayRepository#enable($id)") {
                             if (DEBUG) {
@@ -303,8 +294,12 @@
 private interface DisplayConnectionListener : DisplayListener {
 
     override fun onDisplayConnected(id: Int) {}
+
     override fun onDisplayDisconnected(id: Int) {}
+
     override fun onDisplayAdded(id: Int) {}
+
     override fun onDisplayRemoved(id: Int) {}
+
     override fun onDisplayChanged(id: Int) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
index 3f21533..87b0f01 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
@@ -19,9 +19,12 @@
 import android.os.Bundle
 import android.view.View
 import android.widget.TextView
+import androidx.core.view.updatePadding
+import com.android.systemui.biometrics.Utils
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIBottomSheetDialog
 import com.android.systemui.statusbar.policy.ConfigurationController
+import kotlin.math.max
 
 /**
  * Dialog used to decide what to do with a connected display.
@@ -58,5 +61,23 @@
                 onCancelMirroring.onClick(null)
             }
         }
+        setupInsets()
+    }
+
+    private fun setupInsets() {
+        // This avoids overlap between dialog content and navigation bars.
+        requireViewById<View>(R.id.cd_bottom_sheet).apply {
+            val navbarInsets = Utils.getNavbarInsets(context)
+            val defaultDialogBottomInset =
+                context.resources.getDimensionPixelSize(R.dimen.dialog_bottom_padding)
+            // we only care about the bottom inset as in all other configuration where navigations
+            // are in other display sides there is no overlap with the dialog.
+            updatePadding(bottom = max(navbarInsets.bottom, defaultDialogBottomInset))
+        }
+    }
+
+    override fun onConfigurationChanged() {
+        super.onConfigurationChanged()
+        setupInsets()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
index 83c239f..dd58604 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
@@ -17,15 +17,19 @@
 package com.android.systemui.flags
 
 import android.util.Log
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.flags.ConditionalRestarter.Condition
+import com.android.systemui.util.kotlin.UnflaggedApplication
+import com.android.systemui.util.kotlin.UnflaggedBackground
 import java.util.concurrent.TimeUnit
 import javax.inject.Inject
 import javax.inject.Named
-import kotlinx.coroutines.CoroutineDispatcher
+import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.transformLatest
 import kotlinx.coroutines.launch
 
 /** Restarts the process after all passed in [Condition]s are true. */
@@ -35,11 +39,10 @@
     private val systemExitRestarter: SystemExitRestarter,
     private val conditions: Set<@JvmSuppressWildcards Condition>,
     @Named(RESTART_DELAY) private val restartDelaySec: Long,
-    @Application private val applicationScope: CoroutineScope,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    @UnflaggedApplication private val applicationScope: CoroutineScope,
+    @UnflaggedBackground private val backgroundDispatcher: CoroutineContext,
 ) : Restarter {
 
-    private var restartJob: Job? = null
     private var pendingReason = ""
     private var androidRestartRequested = false
 
@@ -57,17 +60,19 @@
     private fun scheduleRestart(reason: String = "") {
         pendingReason = if (reason.isEmpty()) pendingReason else reason
 
-        if (conditions.all { c -> c.canRestartNow(this::scheduleRestart) }) {
-            if (restartJob == null) {
-                restartJob =
-                    applicationScope.launch(backgroundDispatcher) {
+        applicationScope.launch(backgroundDispatcher) {
+            combine(conditions.map { condition -> condition.canRestartNow }) { it.all { it } }
+                // Once all conditions are met, delay.
+                .transformLatest { allConditionsMet ->
+                    if (allConditionsMet) {
                         delay(TimeUnit.SECONDS.toMillis(restartDelaySec))
-                        restartNow()
+                        emit(Unit)
                     }
-            }
-        } else {
-            restartJob?.cancel()
-            restartJob = null
+                }
+                // Once we have successfully delayed _once_, continue to restart.
+                .first()
+
+            restartNow()
         }
     }
 
@@ -94,7 +99,7 @@
          * multiple [Condition]s are being checked. If any one [Condition] returns false, all the
          * [Condition]s will need to be rechecked on the next restart attempt.
          */
-        fun canRestartNow(retryFn: () -> Unit): Boolean
+        val canRestartNow: Flow<Boolean>
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/NotOccludedCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/NotOccludedCondition.kt
new file mode 100644
index 0000000..f5b30cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/NotOccludedCondition.kt
@@ -0,0 +1,24 @@
+package com.android.systemui.flags
+
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import dagger.Lazy
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** Returns true when the device is "asleep" as defined by the [WakefullnessLifecycle]. */
+class NotOccludedCondition
+@Inject
+constructor(
+    private val keyguardTransitionInteractorLazy: Lazy<KeyguardTransitionInteractor>,
+) : ConditionalRestarter.Condition {
+
+    override val canRestartNow: Flow<Boolean>
+        get() {
+            return keyguardTransitionInteractorLazy
+                .get()
+                .transitionValue(KeyguardState.OCCLUDED)
+                .map { it == 0f }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
index 3120638..dc08570 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
@@ -16,34 +16,34 @@
 
 package com.android.systemui.flags
 
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.statusbar.policy.BatteryController
+import dagger.Lazy
 import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
 
 /** Returns true when the device is plugged in. */
 class PluggedInCondition
 @Inject
 constructor(
-    private val batteryController: BatteryController,
+    private val batteryControllerLazy: Lazy<BatteryController>,
 ) : ConditionalRestarter.Condition {
 
-    var listenersAdded = false
-    var retryFn: (() -> Unit)? = null
-
-    val batteryCallback =
-        object : BatteryController.BatteryStateChangeCallback {
-            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
-                retryFn?.invoke()
+    override val canRestartNow = conflatedCallbackFlow {
+        val batteryCallback =
+            object : BatteryController.BatteryStateChangeCallback {
+                override fun onBatteryLevelChanged(
+                    level: Int,
+                    pluggedIn: Boolean,
+                    charging: Boolean
+                ) {
+                    trySend(pluggedIn)
+                }
             }
-        }
+        batteryControllerLazy.get().addCallback(batteryCallback)
 
-    override fun canRestartNow(retryFn: () -> Unit): Boolean {
-        if (!listenersAdded) {
-            listenersAdded = true
-            batteryController.addCallback(batteryCallback)
-        }
+        trySend(batteryControllerLazy.get().isPluggedIn)
 
-        this.retryFn = retryFn
-
-        return batteryController.isPluggedIn
+        awaitClose { batteryControllerLazy.get().removeCallback(batteryCallback) }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/RefactorFlag.kt b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlag.kt
index 7ccc26c..4a5cc64 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/RefactorFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlag.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.flags
 
-import android.util.Log
 import com.android.systemui.Dependency
 
 /**
@@ -65,8 +64,7 @@
      * }
      * ````
      */
-    fun assertInLegacyMode() =
-        check(!isEnabled) { "Legacy code path not supported when $flagName is enabled." }
+    fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, flagName)
 
     /**
      * Called to ensure code is only run when the flag is enabled. This protects users from the
@@ -81,13 +79,8 @@
      * }
      * ```
      */
-    fun isUnexpectedlyInLegacyMode(): Boolean {
-        if (!isEnabled) {
-            val message = "New code path expects $flagName to be enabled."
-            Log.wtf(TAG, message, Exception(message))
-        }
-        return !isEnabled
-    }
+    fun isUnexpectedlyInLegacyMode(): Boolean =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, flagName)
 
     companion object {
         private const val TAG = "RefactorFlag"
diff --git a/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt
new file mode 100644
index 0000000..2aa397f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.util.Log
+
+/**
+ * Utilities for writing your own objects to uphold refactor flag conventions.
+ *
+ * Example usage:
+ * ```
+ * object SomeRefactor {
+ *     const val FLAG_NAME = Flags.SOME_REFACTOR
+ *     @JvmStatic inline val isEnabled get() = Flags.someRefactor()
+ *     @JvmStatic inline fun isUnexpectedlyInLegacyMode() =
+ *         RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+ *     @JvmStatic inline fun assertInLegacyMode() =
+ *         RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+ * }
+ * ```
+ */
+@Suppress("NOTHING_TO_INLINE")
+object RefactorFlagUtils {
+    /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     *
+     * Example usage:
+     * ```
+     * public void setNewController(SomeController someController) {
+     *     if (SomeRefactor.isUnexpectedlyInLegacyMode()) return;
+     *     mSomeController = someController;
+     * }
+     * ```
+     */
+    inline fun isUnexpectedlyInLegacyMode(isEnabled: Boolean, flagName: Any): Boolean {
+        val inLegacyMode = !isEnabled
+        if (inLegacyMode) {
+            val message = "New code path expects $flagName to be enabled."
+            Log.wtf("RefactorFlag", message, IllegalStateException(message))
+        }
+        return inLegacyMode
+    }
+
+    /**
+     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+     * the flag is enabled to ensure that the refactor author catches issues in testing.
+     *
+     * Example usage:
+     * ```
+     * public void setSomeLegacyController(SomeController someController) {
+     *     SomeRefactor.assertInLegacyMode();
+     *     mSomeController = someController;
+     * }
+     * ````
+     */
+    inline fun assertInLegacyMode(isEnabled: Boolean, flagName: Any) =
+        check(!isEnabled) { "Legacy code path not supported when $flagName is enabled." }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
index 49e61af..3c9bc36 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
@@ -16,34 +16,19 @@
 
 package com.android.systemui.flags
 
-import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import dagger.Lazy
 import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
 
 /** Returns true when the device is "asleep" as defined by the [WakefullnessLifecycle]. */
 class ScreenIdleCondition
 @Inject
-constructor(
-    private val wakefulnessLifecycle: WakefulnessLifecycle,
-) : ConditionalRestarter.Condition {
+constructor(private val powerInteractorLazy: Lazy<PowerInteractor>) :
+    ConditionalRestarter.Condition {
 
-    var listenersAdded = false
-    var retryFn: (() -> Unit)? = null
-
-    val observer =
-        object : WakefulnessLifecycle.Observer {
-            override fun onFinishedGoingToSleep() {
-                retryFn?.invoke()
-            }
+    override val canRestartNow: Flow<Boolean>
+        get() {
+            return powerInteractorLazy.get().isAsleep
         }
-
-    override fun canRestartNow(retryFn: () -> Unit): Boolean {
-        if (!listenersAdded) {
-            listenersAdded = true
-            wakefulnessLifecycle.addObserver(observer)
-        }
-
-        this.retryFn = retryFn
-
-        return wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index bc07139..6f491d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -36,9 +36,9 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
 import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
+import com.android.systemui.util.TraceUtils.Companion.runBlocking
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.runBlocking
 
 class CustomizationProvider :
     ContentProvider(), SystemUIAppComponentFactoryBase.ContextInitializer {
@@ -132,7 +132,7 @@
             throw UnsupportedOperationException()
         }
 
-        return runBlocking(mainDispatcher) { insertSelection(values) }
+        return runBlocking("$TAG#insert", mainDispatcher) { insertSelection(values) }
     }
 
     override fun query(
@@ -142,7 +142,7 @@
         selectionArgs: Array<out String>?,
         sortOrder: String?,
     ): Cursor? {
-        return runBlocking(mainDispatcher) {
+        return runBlocking("$TAG#query", mainDispatcher) {
             when (uriMatcher.match(uri)) {
                 MATCH_CODE_ALL_AFFORDANCES -> queryAffordances()
                 MATCH_CODE_ALL_SLOTS -> querySlots()
@@ -172,7 +172,7 @@
             throw UnsupportedOperationException()
         }
 
-        return runBlocking(mainDispatcher) { deleteSelection(uri, selectionArgs) }
+        return runBlocking("$TAG#delete", mainDispatcher) { deleteSelection(uri, selectionArgs) }
     }
 
     override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 3cdff76..6a0d595 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -56,6 +56,10 @@
 import com.android.systemui.user.data.model.SelectionStatus
 import com.android.systemui.user.data.repository.UserRepository
 import com.google.errorprone.annotations.CompileTimeConstant
+import java.io.PrintWriter
+import java.util.Arrays
+import java.util.stream.Collectors
+import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
@@ -78,10 +82,6 @@
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import java.io.PrintWriter
-import java.util.Arrays
-import java.util.stream.Collectors
-import javax.inject.Inject
 
 /**
  * API to run face authentication and detection for device entry / on keyguard (as opposed to the
@@ -368,10 +368,12 @@
         return arrayOf(
             Pair(
                 and(
-                    displayStateInteractor.isDefaultDisplayOff,
-                    keyguardTransitionInteractor.isFinishedInStateWhere(
-                            KeyguardState::deviceIsAwakeInState),
-                ).isFalse(),
+                        displayStateInteractor.isDefaultDisplayOff,
+                        keyguardTransitionInteractor.isFinishedInStateWhere(
+                            KeyguardState::deviceIsAwakeInState
+                        ),
+                    )
+                    .isFalse(),
                 // this can happen if an app is requesting for screen off, the display can
                 // turn off without wakefulness.isStartingToSleepOrAsleep calls
                 "displayIsNotOffWhileFullyTransitionedToAwake",
@@ -381,10 +383,7 @@
                 "isFaceAuthEnrolledAndEnabled"
             ),
             Pair(keyguardRepository.isKeyguardGoingAway.isFalse(), "keyguardNotGoingAway"),
-            Pair(
-                powerInteractor.isAsleep.isFalse(),
-                "deviceNotAsleep"
-            ),
+            Pair(powerInteractor.isAsleep.isFalse(), "deviceNotAsleep"),
             Pair(
                 keyguardInteractor.isSecureCameraActive
                     .isFalse()
@@ -430,10 +429,15 @@
     private val faceAuthCallback =
         object : FaceManager.AuthenticationCallback() {
             override fun onAuthenticationFailed() {
-                _authenticationStatus.value = FailedFaceAuthenticationStatus()
                 _isAuthenticated.value = false
                 faceAuthLogger.authenticationFailed()
-                onFaceAuthRequestCompleted()
+                if (!_isLockedOut.value) {
+                    // onAuthenticationError gets invoked before onAuthenticationFailed when the
+                    // last auth attempt locks out face authentication.
+                    // Skip updating the authentication status in such a scenario.
+                    _authenticationStatus.value = FailedFaceAuthenticationStatus()
+                    onFaceAuthRequestCompleted()
+                }
             }
 
             override fun onAuthenticationAcquired(acquireInfo: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index d44a9d8..95ac0d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.util.TraceUtils.Companion.launch
 import com.android.systemui.util.kotlin.Utils.Companion.toQuad
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
 import com.android.systemui.util.kotlin.sample
@@ -43,7 +44,6 @@
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.launch
 
 @SysUISingleton
 class FromLockscreenTransitionInteractor
@@ -136,7 +136,7 @@
 
     private fun listenForLockscreenToDreaming() {
         val invalidFromStates = setOf(KeyguardState.AOD, KeyguardState.DOZING)
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToDreaming") {
             keyguardInteractor.isAbleToDream
                 .sample(
                     combine(
@@ -169,7 +169,7 @@
     }
 
     private fun listenForLockscreenToPrimaryBouncer() {
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToPrimaryBouncer") {
             keyguardInteractor.primaryBouncerShowing
                 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
@@ -184,7 +184,7 @@
     }
 
     private fun listenForLockscreenToAlternateBouncer() {
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToAlternateBouncer") {
             keyguardInteractor.alternateBouncerShowing
                 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
@@ -202,7 +202,7 @@
     /* Starts transitions when manually dragging up the bouncer from the lockscreen. */
     private fun listenForLockscreenToPrimaryBouncerDragging() {
         var transitionId: UUID? = null
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToPrimaryBouncerDragging") {
             shadeRepository.shadeModel
                 .sample(
                     combine(
@@ -287,7 +287,7 @@
             return
         }
 
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToGone") {
             keyguardInteractor.isKeyguardGoingAway
                 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
@@ -304,7 +304,7 @@
             return
         }
 
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToGoneDragging") {
             keyguardInteractor.isKeyguardGoingAway
                 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
@@ -317,7 +317,7 @@
     }
 
     private fun listenForLockscreenToOccluded() {
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToOccluded") {
             keyguardInteractor.isKeyguardOccluded
                 .sample(transitionInteractor.startedKeyguardState, ::Pair)
                 .collect { (isOccluded, keyguardState) ->
@@ -329,7 +329,7 @@
     }
 
     private fun listenForLockscreenToAodOrDozing() {
-        scope.launch {
+        scope.launch("$TAG#listenForLockscreenToAodOrDozing") {
             powerInteractor.isAsleep
                 .sample(
                     combine(
@@ -375,6 +375,7 @@
     }
 
     companion object {
+        const val TAG = "FromLockscreenTransitionInteractor"
         private val DEFAULT_DURATION = 400.milliseconds
         val TO_DREAMING_DURATION = 933.milliseconds
         val TO_OCCLUDED_DURATION = 450.milliseconds
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 de791aa..fe9370f 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
@@ -23,7 +23,6 @@
 import android.content.Intent
 import android.util.Log
 import com.android.internal.widget.LockPatternUtils
-import com.android.systemui.res.R
 import com.android.systemui.animation.DialogLaunchAnimator
 import com.android.systemui.animation.Expandable
 import com.android.systemui.dagger.SysUISingleton
@@ -44,11 +43,12 @@
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.TraceUtils.Companion.traceAsync
+import com.android.systemui.util.TraceUtils.Companion.withContext
 import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -59,7 +59,6 @@
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.withContext
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
@@ -417,10 +416,8 @@
     }
 
     private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
-        traceAsync(TAG, "isFeatureDisabledByDevicePolicy") {
-            withContext(backgroundDispatcher) {
-                devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
-            }
+        withContext("$TAG#isFeatureDisabledByDevicePolicy", backgroundDispatcher) {
+            devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
         }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
index 565bf24..baa07c1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
@@ -95,7 +95,7 @@
         tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true)
         initialValue
     }
-    return this.pairwiseBy(initialValueFun) { prevVal, newVal: Boolean ->
+    return this.pairwiseBy(initialValueFun) { prevVal: Boolean, newVal: Boolean ->
         if (prevVal != newVal) {
             tableLogBuffer.logChange(columnPrefix, columnName, newVal)
         }
@@ -114,7 +114,7 @@
         tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true)
         initialValue
     }
-    return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int ->
+    return this.pairwiseBy(initialValueFun) { prevVal: Int, newVal: Int ->
         if (prevVal != newVal) {
             tableLogBuffer.logChange(columnPrefix, columnName, newVal)
         }
@@ -133,7 +133,7 @@
         tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true)
         initialValue
     }
-    return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int? ->
+    return this.pairwiseBy(initialValueFun) { prevVal: Int?, newVal: Int? ->
         if (prevVal != newVal) {
             tableLogBuffer.logChange(columnPrefix, columnName, newVal)
         }
@@ -152,7 +152,7 @@
         tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true)
         initialValue
     }
-    return this.pairwiseBy(initialValueFun) { prevVal, newVal: String? ->
+    return this.pairwiseBy(initialValueFun) { prevVal: String?, newVal: String? ->
         if (prevVal != newVal) {
             tableLogBuffer.logChange(columnPrefix, columnName, newVal)
         }
@@ -176,7 +176,7 @@
         )
         initialValue
     }
-    return this.pairwiseBy(initialValueFun) { prevVal, newVal: List<T> ->
+    return this.pairwiseBy(initialValueFun) { prevVal: List<T>, newVal: List<T> ->
         if (prevVal != newVal) {
             // TODO(b/267761156): Can we log list changes without using toString?
             tableLogBuffer.logChange(columnPrefix, columnName, newVal.toString())
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
index d8cab6a..1962119 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
@@ -23,7 +23,6 @@
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_CAST as METRICS_CREATION_SOURCE_CAST
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER as METRICS_CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN as METRICS_CREATION_SOURCE_UNKNOWN
-import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED as METRICS_STATE_PERMISSION_REQUEST_DISPLAYED
 import com.android.systemui.dagger.SysUISingleton
 import javax.inject.Inject
 
@@ -53,8 +52,30 @@
         }
     }
 
-    fun notifyPermissionRequestDisplayed() {
-        notifyToServer(METRICS_STATE_PERMISSION_REQUEST_DISPLAYED, SessionCreationSource.UNKNOWN)
+    /**
+     * Request to log that the permission request was displayed.
+     *
+     * @param hostUid The UID of the package that initiates MediaProjection.
+     */
+    fun notifyPermissionRequestDisplayed(hostUid: Int) {
+        try {
+            service.notifyPermissionRequestDisplayed(hostUid)
+        } catch (e: RemoteException) {
+            Log.e(TAG, "Error notifying server of projection displayed", e)
+        }
+    }
+
+    /**
+     * Request to log that the app selector was displayed.
+     *
+     * @param hostUid The UID of the package that initiates MediaProjection.
+     */
+    fun notifyAppSelectorDisplayed(hostUid: Int) {
+        try {
+            service.notifyAppSelectorDisplayed(hostUid)
+        } catch (e: RemoteException) {
+            Log.e(TAG, "Error notifying server of app selector displayed", e)
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt
index 0bbcfd9..04d5566 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt
@@ -92,6 +92,7 @@
         component =
             componentFactory.create(
                 hostUserHandle = hostUserHandle,
+                hostUid = hostUid,
                 callingPackage = callingPackage,
                 view = this,
                 resultHandler = this,
@@ -305,6 +306,17 @@
                 )
         }
 
+    private val hostUid: Int
+        get() {
+            if (!intent.hasExtra(EXTRA_HOST_APP_UID)) {
+                error(
+                    "MediaProjectionAppSelectorActivity should be provided with " +
+                        "$EXTRA_HOST_APP_UID extra"
+                )
+            }
+            return intent.getIntExtra(EXTRA_HOST_APP_UID, /* defaultValue= */ -1)
+        }
+
     companion object {
         const val TAG = "MediaProjectionAppSelectorActivity"
 
@@ -315,8 +327,16 @@
          */
         const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver"
 
-        /** UID of the app that originally launched the media projection flow (host app user) */
+        /**
+         * User on the device that launched the media projection flow. (Primary, Secondary, Guest,
+         * Work, etc)
+         */
         const val EXTRA_HOST_APP_USER_HANDLE = "launched_from_user_handle"
+        /**
+         * The kernel user-ID that has been assigned to the app that originally launched the media
+         * projection flow.
+         */
+        const val EXTRA_HOST_APP_UID = "launched_from_host_uid"
         const val KEY_CAPTURE_TARGET = "capture_region"
 
         /** Set up intent for the [ChooserActivity] */
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 8c6f307..d247122 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -57,6 +57,8 @@
 
 @Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUserHandle
 
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUid
+
 @Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope
 
 @Module(
@@ -143,6 +145,7 @@
         /** Create a factory to inject the activity into the graph */
         fun create(
             @BindsInstance @HostUserHandle hostUserHandle: UserHandle,
+            @BindsInstance @HostUid hostUid: Int,
             @BindsInstance @MediaProjectionAppSelector callingPackage: String?,
             @BindsInstance view: MediaProjectionAppSelectorView,
             @BindsInstance resultHandler: MediaProjectionAppSelectorResultHandler,
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
index 69132d3..67ef119 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
@@ -47,13 +47,14 @@
     private val thumbnailLoader: RecentTaskThumbnailLoader,
     @MediaProjectionAppSelector private val isFirstStart: Boolean,
     private val logger: MediaProjectionMetricsLogger,
+    @HostUid private val hostUid: Int,
 ) {
 
     fun init() {
         // Only log during the first start of the app selector.
         // Don't log when the app selector restarts due to a config change.
         if (isFirstStart) {
-            logger.notifyPermissionProgress(STATE_APP_SELECTOR_DISPLAYED)
+            logger.notifyAppSelectorDisplayed(hostUid)
         }
 
         scope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
index 922f7e0..f7cc589 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
@@ -252,7 +252,7 @@
         mDialog.show();
 
         if (savedInstanceState == null) {
-            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed();
+            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(mUid);
         }
     }
 
@@ -330,6 +330,9 @@
                         projection.asBinder());
                 intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
                         getHostUserHandle());
+                intent.putExtra(
+                        MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID,
+                        getLaunchedFromUid());
                 intent.putExtra(EXTRA_USER_REVIEW_GRANTED_CONSENT, mReviewGrantedConsentRequired);
                 intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index e27a59c..f37f58d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -47,6 +47,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.res.R;
 import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -71,6 +72,7 @@
     private final FeatureFlags mFlags;
     private final PanelInteractor mPanelInteractor;
     private final MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
+    private final UserContextProvider mUserContextProvider;
 
     private long mMillisUntilFinished = 0;
 
@@ -91,7 +93,8 @@
             KeyguardStateController keyguardStateController,
             DialogLaunchAnimator dialogLaunchAnimator,
             PanelInteractor panelInteractor,
-            MediaProjectionMetricsLogger mediaProjectionMetricsLogger
+            MediaProjectionMetricsLogger mediaProjectionMetricsLogger,
+            UserContextProvider userContextProvider
     ) {
         super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
@@ -103,6 +106,7 @@
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mPanelInteractor = panelInteractor;
         mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger;
+        mUserContextProvider = userContextProvider;
     }
 
     @Override
@@ -195,7 +199,8 @@
                 dialog.show();
             }
 
-            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed();
+            int uid = mUserContextProvider.getUserContext().getUserId();
+            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(uid);
 
             return false;
         };
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandler.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandler.kt
rename to packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
index 9d10072..905d8ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.base.actions
 
+import android.app.PendingIntent
 import android.content.Intent
 import android.view.View
 import com.android.internal.jank.InteractionJankMonitor
@@ -29,7 +30,7 @@
  * dismissing and tile from-view animations.
  */
 @SysUISingleton
-class QSTileIntentUserActionHandler
+class QSTileIntentUserInputHandler
 @Inject
 constructor(private val activityStarter: ActivityStarter) {
 
@@ -43,4 +44,19 @@
             }
         activityStarter.postStartActivityDismissingKeyguard(intent, 0, animationController)
     }
+
+    // TODO(b/249804373): make sure to allow showing activities over the lockscreen. See b/292112939
+    fun handle(view: View?, pendingIntent: PendingIntent) {
+        if (!pendingIntent.isActivity) {
+            return
+        }
+        val animationController: ActivityLaunchAnimator.Controller? =
+            view?.let {
+                ActivityLaunchAnimator.Controller.fromView(
+                    it,
+                    InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE,
+                )
+            }
+        activityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/DataUpdateTrigger.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/DataUpdateTrigger.kt
new file mode 100644
index 0000000..4f25d3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/DataUpdateTrigger.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.base.interactor
+
+/** Event that triggers data update */
+sealed interface DataUpdateTrigger {
+    /**
+     * State update is requested in a response to a user action.
+     * - [action] is the action that happened
+     * - [tileData] is the data state of the tile when that action took place
+     */
+    class UserInput<T>(val input: QSTileInput<T>) : DataUpdateTrigger
+
+    /** Force update current state. This is passed when the view needs a new state to show */
+    data object ForceUpdate : DataUpdateTrigger
+
+    /** The data is requested loaded for the first time */
+    data object InitialRequest : DataUpdateTrigger
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataInteractor.kt
index 7a22e3c..a3e3850 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataInteractor.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.qs.tiles.base.interactor
 
-import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 
@@ -29,14 +28,20 @@
 interface QSTileDataInteractor<DATA_TYPE> {
 
     /**
-     * Returns the data to be mapped to [QSTileState]. Make sure to start the flow [Flow.onStart]
-     * with the current state to update the tile as soon as possible.
+     * Returns a data flow scoped to the user. This means the subscription will live when the tile
+     * is listened for the [userId]. It's cancelled when the tile is not listened or the user
+     * changes.
+     *
+     * You can use [Flow.onStart] on the returned to update the tile with the current state as soon
+     * as possible.
      */
-    fun tileData(qsTileDataRequest: QSTileDataRequest): Flow<DATA_TYPE>
+    fun tileData(userId: Int, triggers: Flow<DataUpdateTrigger>): Flow<DATA_TYPE>
 
     /**
-     * Returns tile availability - whether this device currently supports this tile. Make sure to
-     * start the flow [Flow.onStart] with the current state to update the tile as soon as possible.
+     * Returns tile availability - whether this device currently supports this tile.
+     *
+     * You can use [Flow.onStart] on the returned to update the tile with the current state as soon
+     * as possible.
      */
-    fun availability(): Flow<Boolean>
+    fun availability(userId: Int): Flow<Boolean>
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileInput.kt
similarity index 78%
rename from packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
rename to packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileInput.kt
index 0aa6b0b..102fa36 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileDataRequest.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileInput.kt
@@ -16,7 +16,11 @@
 
 package com.android.systemui.qs.tiles.base.interactor
 
-data class QSTileDataRequest(
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+
+/** @see QSTileUserActionInteractor.handleInput */
+data class QSTileInput<T>(
     val userId: Int,
-    val trigger: StateUpdateTrigger,
+    val action: QSTileUserAction,
+    val data: T,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
index 14fc639..09d7a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
@@ -17,13 +17,14 @@
 package com.android.systemui.qs.tiles.base.interactor
 
 import android.annotation.WorkerThread
-import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 
 interface QSTileUserActionInteractor<DATA_TYPE> {
-
     /**
-     * Processes user input based on [userAction] and [currentData]. It's safe to run long running
-     * computations inside this function in this.
+     * Processes user input based on [QSTileInput.userId], [QSTileInput.action], and
+     * [QSTileInput.data]. It's guaranteed that [QSTileInput.userId] is the same as the id passed to
+     * [QSTileDataInteractor] to get [QSTileInput.data].
+     *
+     * It's safe to run long running computations inside this function in this.
      */
-    @WorkerThread suspend fun handleInput(userAction: QSTileUserAction, currentData: DATA_TYPE)
+    @WorkerThread suspend fun handleInput(input: QSTileInput<DATA_TYPE>)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/StateUpdateTrigger.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/StateUpdateTrigger.kt
deleted file mode 100644
index ffe38dd..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/StateUpdateTrigger.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles.base.interactor
-
-import com.android.systemui.qs.tiles.viewmodel.QSTileState
-import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
-
-sealed interface StateUpdateTrigger {
-    class UserAction<T>(val action: QSTileUserAction, val tileState: QSTileState, val tileData: T) :
-        StateUpdateTrigger
-    data object ForceUpdate : StateUpdateTrigger
-    data object InitialRequest : StateUpdateTrigger
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
index f8de365..4dc1c82 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.log.dagger.QSTilesLogBuffers
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.pipeline.shared.TileSpec
-import com.android.systemui.qs.tiles.base.interactor.StateUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import com.android.systemui.statusbar.StatusBarState
@@ -128,10 +128,21 @@
             )
     }
 
+    fun logForceUpdate(tileSpec: TileSpec) {
+        tileSpec
+            .getLogBuffer()
+            .log(tileSpec.getLogTag(), LogLevel.DEBUG, {}, { "tile data force update" })
+    }
+
+    fun logInitialRequest(tileSpec: TileSpec) {
+        tileSpec
+            .getLogBuffer()
+            .log(tileSpec.getLogTag(), LogLevel.DEBUG, {}, { "tile data initial update" })
+    }
+
     /** Tracks state changes based on the data and trigger event. */
     fun <T> logStateUpdate(
         tileSpec: TileSpec,
-        trigger: StateUpdateTrigger,
         tileState: QSTileState,
         data: T,
     ) {
@@ -141,11 +152,10 @@
                 tileSpec.getLogTag(),
                 LogLevel.DEBUG,
                 {
-                    str1 = trigger.toLogString()
-                    str2 = tileState.toLogString()
-                    str3 = data.toString().take(DATA_MAX_LENGTH)
+                    str1 = tileState.toLogString()
+                    str2 = data.toString().take(DATA_MAX_LENGTH)
                 },
-                { "tile state update: trigger=$str1, state=$str2, data=$str3" }
+                { "tile state update: state=$str1, data=$str2" }
             )
     }
 
@@ -162,11 +172,11 @@
             }
         }
 
-    private fun StateUpdateTrigger.toLogString(): String =
+    private fun DataUpdateTrigger.toLogString(): String =
         when (this) {
-            is StateUpdateTrigger.ForceUpdate -> "force"
-            is StateUpdateTrigger.InitialRequest -> "init"
-            is StateUpdateTrigger.UserAction<*> -> action.toLogString()
+            is DataUpdateTrigger.ForceUpdate -> "force"
+            is DataUpdateTrigger.InitialRequest -> "init"
+            is DataUpdateTrigger.UserInput<*> -> input.action.toLogString()
         }
 
     private fun QSTileUserAction.toLogString(): String =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/BaseQSTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/BaseQSTileViewModel.kt
index 2114751..14de5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/BaseQSTileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/BaseQSTileViewModel.kt
@@ -22,12 +22,12 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
 import com.android.systemui.qs.tiles.base.interactor.DisabledByPolicyInteractor
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
-import com.android.systemui.qs.tiles.base.interactor.QSTileDataRequest
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
-import com.android.systemui.qs.tiles.base.interactor.StateUpdateTrigger
 import com.android.systemui.qs.tiles.base.logging.QSTileLogger
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
 import com.android.systemui.qs.tiles.viewmodel.QSTileLifecycle
@@ -35,26 +35,31 @@
 import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
-import com.android.systemui.util.kotlin.sample
+import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.util.kotlin.throttle
+import com.android.systemui.util.time.SystemClock
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.channels.BufferOverflow
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.cancellable
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
@@ -66,6 +71,7 @@
  *
  * Inject [BaseQSTileViewModel.Factory] to create a new instance of this class.
  */
+@OptIn(ExperimentalCoroutinesApi::class)
 class BaseQSTileViewModel<DATA_TYPE>
 @VisibleForTesting
 constructor(
@@ -74,9 +80,11 @@
     private val tileDataInteractor: QSTileDataInteractor<DATA_TYPE>,
     private val mapper: QSTileDataToStateMapper<DATA_TYPE>,
     private val disabledByPolicyInteractor: DisabledByPolicyInteractor,
+    userRepository: UserRepository,
     private val falsingManager: FalsingManager,
     private val qsTileAnalytics: QSTileAnalytics,
     private val qsTileLogger: QSTileLogger,
+    private val systemClock: SystemClock,
     private val backgroundDispatcher: CoroutineDispatcher,
     private val tileScope: CoroutineScope,
 ) : QSTileViewModel {
@@ -88,9 +96,11 @@
         @Assisted tileDataInteractor: QSTileDataInteractor<DATA_TYPE>,
         @Assisted mapper: QSTileDataToStateMapper<DATA_TYPE>,
         disabledByPolicyInteractor: DisabledByPolicyInteractor,
+        userRepository: UserRepository,
         falsingManager: FalsingManager,
         qsTileAnalytics: QSTileAnalytics,
         qsTileLogger: QSTileLogger,
+        systemClock: SystemClock,
         @Background backgroundDispatcher: CoroutineDispatcher,
     ) : this(
         config,
@@ -98,28 +108,30 @@
         tileDataInteractor,
         mapper,
         disabledByPolicyInteractor,
+        userRepository,
         falsingManager,
         qsTileAnalytics,
         qsTileLogger,
+        systemClock,
         backgroundDispatcher,
         CoroutineScope(SupervisorJob())
     )
 
+    private val userIds: MutableStateFlow<Int> =
+        MutableStateFlow(userRepository.getSelectedUserInfo().id)
     private val userInputs: MutableSharedFlow<QSTileUserAction> =
         MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
-    private val userIds: MutableSharedFlow<Int> =
-        MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
     private val forceUpdates: MutableSharedFlow<Unit> =
         MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
     private val spec
         get() = config.tileSpec
 
-    private lateinit var tileData: SharedFlow<DataWithTrigger<DATA_TYPE>>
+    private lateinit var tileData: SharedFlow<DATA_TYPE>
 
     override lateinit var state: SharedFlow<QSTileState>
     override val isAvailable: StateFlow<Boolean> =
-        tileDataInteractor
-            .availability()
+        userIds
+            .flatMapLatest { tileDataInteractor.availability(it) }
             .flowOn(backgroundDispatcher)
             .stateIn(
                 tileScope,
@@ -162,15 +174,9 @@
                 tileData = createTileDataFlow()
                 state =
                     tileData
-                        // TODO(b/299908705): log data and corresponding tile state
-                        .map { dataWithTrigger ->
-                            mapper.map(config, dataWithTrigger.data).also { state ->
-                                qsTileLogger.logStateUpdate(
-                                    spec,
-                                    dataWithTrigger.trigger,
-                                    state,
-                                    dataWithTrigger.data
-                                )
+                        .map { data ->
+                            mapper.map(config, data).also { state ->
+                                qsTileLogger.logStateUpdate(spec, state, data)
                             }
                         }
                         .flowOn(backgroundDispatcher)
@@ -188,88 +194,99 @@
         currentLifeState = lifecycle
     }
 
-    private fun createTileDataFlow(): SharedFlow<DataWithTrigger<DATA_TYPE>> =
+    private fun createTileDataFlow(): SharedFlow<DATA_TYPE> =
         userIds
             .flatMapLatest { userId ->
-                merge(
-                        userInputFlow(userId),
-                        forceUpdates.map { StateUpdateTrigger.ForceUpdate },
-                    )
-                    .onStart { emit(StateUpdateTrigger.InitialRequest) }
-                    .map { trigger -> QSTileDataRequest(userId, trigger) }
+                val updateTriggers =
+                    merge(
+                            userInputFlow(userId),
+                            forceUpdates
+                                .map { DataUpdateTrigger.ForceUpdate }
+                                .onEach { qsTileLogger.logForceUpdate(spec) },
+                        )
+                        .onStart {
+                            emit(DataUpdateTrigger.InitialRequest)
+                            qsTileLogger.logInitialRequest(spec)
+                        }
+                tileDataInteractor
+                    .tileData(userId, updateTriggers)
+                    .cancellable()
+                    .flowOn(backgroundDispatcher)
             }
-            .flatMapLatest { request ->
-                // 1) get an updated data source
-                // 2) process user input, possibly triggering new data to be emitted
-                // This handles the case when the data isn't buffered in the interactor
-                // TODO(b/299908705): Log events that trigger data flow to update
-                val dataFlow = tileDataInteractor.tileData(request)
-                if (request.trigger is StateUpdateTrigger.UserAction<*>) {
-                    userActionInteractor.handleInput(
-                        request.trigger.action,
-                        request.trigger.tileData as DATA_TYPE,
-                    )
-                }
-                dataFlow.map { DataWithTrigger(it, request.trigger) }
-            }
-            .flowOn(backgroundDispatcher)
             .shareIn(
                 tileScope,
                 SharingStarted.WhileSubscribed(),
                 replay = 1, // we only care about the most recent value
             )
 
-    private fun userInputFlow(userId: Int): Flow<StateUpdateTrigger> {
-        data class StateWithData<T>(val state: QSTileState, val data: T)
-
-        return when (config.policy) {
-                is QSTilePolicy.NoRestrictions -> userInputs
-                is QSTilePolicy.Restricted ->
-                    userInputs.filter { action ->
-                        val result =
-                            disabledByPolicyInteractor.isDisabled(
-                                userId,
-                                config.policy.userRestriction
-                            )
-                        !disabledByPolicyInteractor.handlePolicyResult(result).also { isDisabled ->
-                            if (isDisabled) {
-                                qsTileLogger.logUserActionRejectedByPolicy(action, spec)
-                            }
-                        }
-                    }
-            }
-            .filter { action ->
-                val isFalseAction =
-                    when (action) {
-                        is QSTileUserAction.Click ->
-                            falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)
-                        is QSTileUserAction.LongClick ->
-                            falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)
-                    }
-                if (isFalseAction) {
-                    qsTileLogger.logUserActionRejectedByFalsing(action, spec)
-                }
-                !isFalseAction
-            }
-            .throttle(500)
+    /**
+     * Creates a user input flow which:
+     * - filters false inputs with [falsingManager]
+     * - takes care of a tile being disable by policy using [disabledByPolicyInteractor]
+     * - notifies [userActionInteractor] about the action
+     * - logs it accordingly using [qsTileLogger] and [qsTileAnalytics]
+     *
+     * Subscribing to the result flow twice will result in doubling all actions, logs and analytics.
+     */
+    private fun userInputFlow(userId: Int): Flow<DataUpdateTrigger> {
+        return userInputs
+            .filterFalseActions()
+            .filterByPolicy(userId)
+            .throttle(CLICK_THROTTLE_DURATION, systemClock)
             // Skip the input until there is some data
-            .sample(state.combine(tileData) { state, data -> StateWithData(state, data) }) {
-                input,
-                stateWithData ->
-                StateUpdateTrigger.UserAction(input, stateWithData.state, stateWithData.data).also {
-                    qsTileLogger.logUserActionPipeline(
-                        spec,
-                        it.action,
-                        stateWithData.state,
-                        stateWithData.data
-                    )
-                    qsTileAnalytics.trackUserAction(config, it.action)
-                }
+            .mapNotNull { action ->
+                val state: QSTileState = state.replayCache.lastOrNull() ?: return@mapNotNull null
+                val data: DATA_TYPE = tileData.replayCache.lastOrNull() ?: return@mapNotNull null
+                qsTileLogger.logUserActionPipeline(spec, action, state, data)
+                qsTileAnalytics.trackUserAction(config, action)
+
+                DataUpdateTrigger.UserInput(QSTileInput(userId, action, data))
             }
+            .onEach { userActionInteractor.handleInput(it.input) }
+            .flowOn(backgroundDispatcher)
     }
 
-    private data class DataWithTrigger<T>(val data: T, val trigger: StateUpdateTrigger)
+    private fun Flow<QSTileUserAction>.filterByPolicy(userId: Int): Flow<QSTileUserAction> =
+        when (config.policy) {
+            is QSTilePolicy.NoRestrictions -> this
+            is QSTilePolicy.Restricted ->
+                filter { action ->
+                    val result =
+                        disabledByPolicyInteractor.isDisabled(userId, config.policy.userRestriction)
+                    !disabledByPolicyInteractor.handlePolicyResult(result).also { isDisabled ->
+                        if (isDisabled) {
+                            qsTileLogger.logUserActionRejectedByPolicy(action, spec)
+                        }
+                    }
+                }
+        }
 
+    private fun Flow<QSTileUserAction>.filterFalseActions(): Flow<QSTileUserAction> =
+        filter { action ->
+            val isFalseAction =
+                when (action) {
+                    is QSTileUserAction.Click ->
+                        falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)
+                    is QSTileUserAction.LongClick ->
+                        falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)
+                }
+            if (isFalseAction) {
+                qsTileLogger.logUserActionRejectedByFalsing(action, spec)
+            }
+            !isFalseAction
+        }
+
+    private companion object {
+        const val CLICK_THROTTLE_DURATION = 200L
+    }
+
+    /**
+     * Factory interface for assisted inject. Dagger has bad time supporting generics in assisted
+     * injection factories now. That's why you need to create an interface implementing this one and
+     * annotate it with [dagger.assisted.AssistedFactory].
+     *
+     * ex: @AssistedFactory interface FooFactory : BaseQSTileViewModel.Factory<FooData>
+     */
     interface Factory<T> {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
index 0ccde74..dc5cccc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
@@ -59,7 +59,16 @@
         // This represents a tile that is currently in a disabled state but is still interactable. A
         // disabled state indicates that the tile is not currently active (e.g. wifi disconnected or
         // bluetooth disabled), but is still interactable by the user to modify this state.
-        INACTIVE(Tile.STATE_INACTIVE),
+        INACTIVE(Tile.STATE_INACTIVE);
+
+        companion object {
+            fun valueOf(legacyState: Int): ActivationState =
+                when (legacyState) {
+                    Tile.STATE_ACTIVE -> ACTIVE
+                    Tile.STATE_INACTIVE -> INACTIVE
+                    else -> UNAVAILABLE
+                }
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
index f6299e3..33f55ab 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt
@@ -22,6 +22,7 @@
 import androidx.annotation.GuardedBy
 import com.android.internal.logging.InstanceId
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.qs.QSHost
 import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon
@@ -31,9 +32,7 @@
 import dagger.assisted.AssistedInject
 import java.util.function.Supplier
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.collectIndexed
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
@@ -44,6 +43,7 @@
 class QSTileViewModelAdapter
 @AssistedInject
 constructor(
+    @Application private val applicationScope: CoroutineScope,
     private val qsHost: QSHost,
     @Assisted private val qsTileViewModel: QSTileViewModel,
 ) : QSTile {
@@ -57,25 +57,28 @@
     private val listeningClients: MutableCollection<Any> = mutableSetOf()
 
     // Cancels the jobs when the adapter is no longer alive
-    private val adapterScope = CoroutineScope(SupervisorJob())
+    private var availabilityJob: Job? = null
     // Cancels the jobs when clients stop listening
-    private val listeningScope = CoroutineScope(SupervisorJob())
+    private var stateJob: Job? = null
 
     init {
-        adapterScope.launch {
-            qsTileViewModel.isAvailable.collectIndexed { index, isAvailable ->
-                if (!isAvailable) {
-                    qsHost.removeTile(tileSpec)
-                }
-                // qsTileViewModel.isAvailable flow often starts with isAvailable == true. That's
-                // why we only allow isAvailable == true once and throw an exception afterwards.
-                if (index > 0 && isAvailable) {
-                    // See com.android.systemui.qs.pipeline.domain.model.AutoAddable for additional
-                    // guidance on how to auto add your tile
-                    throw UnsupportedOperationException("Turning on tile is not supported now")
+        availabilityJob =
+            applicationScope.launch {
+                qsTileViewModel.isAvailable.collectIndexed { index, isAvailable ->
+                    if (!isAvailable) {
+                        qsHost.removeTile(tileSpec)
+                    }
+                    // qsTileViewModel.isAvailable flow often starts with isAvailable == true.
+                    // That's
+                    // why we only allow isAvailable == true once and throw an exception afterwards.
+                    if (index > 0 && isAvailable) {
+                        // See com.android.systemui.qs.pipeline.domain.model.AutoAddable for
+                        // additional
+                        // guidance on how to auto add your tile
+                        throw UnsupportedOperationException("Turning on tile is not supported now")
+                    }
                 }
             }
-        }
 
         // QSTileHost doesn't call this when userId is initialized
         userSwitch(qsHost.userId)
@@ -140,25 +143,28 @@
     )
     override fun getMetricsCategory(): Int = 0
 
+    override fun isTileReady(): Boolean = qsTileViewModel.currentState != null
+
     override fun setListening(client: Any?, listening: Boolean) {
         client ?: return
         synchronized(listeningClients) {
             if (listening) {
                 listeningClients.add(client)
                 if (listeningClients.size == 1) {
-                    qsTileViewModel.state
-                        .map { mapState(context, it, qsTileViewModel.config) }
-                        .onEach { legacyState ->
-                            synchronized(callbacks) {
-                                callbacks.forEach { it.onStateChanged(legacyState) }
+                    stateJob =
+                        qsTileViewModel.state
+                            .map { mapState(context, it, qsTileViewModel.config) }
+                            .onEach { legacyState ->
+                                synchronized(callbacks) {
+                                    callbacks.forEach { it.onStateChanged(legacyState) }
+                                }
                             }
-                        }
-                        .launchIn(listeningScope)
+                            .launchIn(applicationScope)
                 }
             } else {
                 listeningClients.remove(client)
                 if (listeningClients.isEmpty()) {
-                    listeningScope.coroutineContext.cancelChildren()
+                    stateJob?.cancel()
                 }
             }
         }
@@ -172,8 +178,8 @@
     }
 
     override fun destroy() {
-        adapterScope.cancel()
-        listeningScope.cancel()
+        stateJob?.cancel()
+        availabilityJob?.cancel()
         qsTileViewModel.onLifecycle(QSTileLifecycle.DEAD)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
index f602da4..ea1205a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
@@ -25,6 +25,7 @@
 import android.content.IntentFilter;
 import android.os.Bundle;
 import android.os.CountDownTimer;
+import android.os.Process;
 import android.os.UserHandle;
 import android.util.Log;
 
@@ -141,6 +142,13 @@
         return UserHandle.of(UserHandle.myUserId());
     }
 
+    /**
+     * MediaProjection host is SystemUI for the screen recorder, so return 'my process uid'
+     */
+    private int getHostUid() {
+        return Process.myUid();
+    }
+
     /** Create a dialog to show screen recording options to the user.
      *  If screen capturing is currently not allowed it will return a dialog
      *  that warns users about it. */
@@ -159,9 +167,18 @@
                 SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER);
 
         return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)
-                ? new ScreenRecordPermissionDialog(context,  getHostUserHandle(), this,
-                    activityStarter, mUserContextProvider, onStartRecordingClicked)
-                : new ScreenRecordDialog(context, this, mUserContextProvider,
+                ? new ScreenRecordPermissionDialog(
+                        context,
+                        getHostUserHandle(),
+                        getHostUid(),
+                        /* controller= */ this,
+                        activityStarter,
+                        mUserContextProvider,
+                        onStartRecordingClicked)
+                : new ScreenRecordDialog(
+                        context,
+                        /* controller= */ this,
+                        mUserContextProvider,
                         onStartRecordingClicked);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index ade93b1..3b3aa53 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -46,6 +46,7 @@
 class ScreenRecordPermissionDialog(
     context: Context,
     private val hostUserHandle: UserHandle,
+    private val hostUid: Int,
     private val controller: RecordingController,
     private val activityStarter: ActivityStarter,
     private val userContextProvider: UserContextProvider,
@@ -88,6 +89,7 @@
                     MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
                     hostUserHandle
                 )
+                intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid)
                 activityStarter.startActivity(intent, /* dismissShade= */ true)
             }
             dismiss()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index aa6bfc3..10d5f59 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -34,11 +34,11 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.settings.DisplayTracker
+import com.android.systemui.util.TraceUtils.Companion.launch
 import javax.inject.Inject
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
 @SysUISingleton
@@ -63,7 +63,9 @@
         user: UserHandle,
         overrideTransition: Boolean,
     ) {
-        applicationScope.launch { launchIntent(intent, options, user, overrideTransition) }
+        applicationScope.launch("$TAG#launchIntentAsync") {
+            launchIntent(intent, options, user, overrideTransition)
+        }
     }
 
     suspend fun launchIntent(
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
index c34fd42..f1c74c1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
@@ -20,10 +20,10 @@
 import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.util.TraceUtils.Companion.launch
+import kotlinx.coroutines.CoroutineScope
 import java.util.function.Consumer
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
 
 /** Processes a screenshot request sent from [ScreenshotHelper]. */
 interface ScreenshotRequestProcessor {
@@ -88,7 +88,7 @@
      *                 thread
      */
     fun processAsync(screenshot: ScreenshotData, callback: Consumer<ScreenshotData>) {
-        mainScope.launch {
+        mainScope.launch({ "$TAG#processAsync" }) {
             val result = process(screenshot)
             callback.accept(result)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
index 14e875d2..d2e4794 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.shade.ShadeExpansionStateManager
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.launch
+import com.android.systemui.util.TraceUtils.Companion.launch
 import kotlinx.coroutines.withContext
 
 /** Provides state from the main SystemUI process on behalf of the Screenshot process. */
@@ -47,7 +47,9 @@
             }
 
             override fun dismissKeyguard(callback: IOnDoneCallback) {
-                lifecycleScope.launch { executeAfterDismissing(callback) }
+                lifecycleScope.launch("IScreenshotProxy#dismissKeyguard") {
+                    executeAfterDismissing(callback)
+                }
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
index cd0cab5..1eae191 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
@@ -20,7 +20,7 @@
 import android.util.Log
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.util.TraceUtils.Companion.tracedAsync
+import com.android.systemui.util.TraceUtils.Companion.async
 import com.google.errorprone.annotations.CanIgnoreReturnValue
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.seconds
@@ -48,7 +48,7 @@
 ) : ScreenshotSoundController {
 
     val player: Deferred<MediaPlayer?> =
-        coroutineScope.tracedAsync("loadCameraSound", bgDispatcher) {
+        coroutineScope.async("loadCameraSound", bgDispatcher) {
             try {
                 soundProvider.getScreenshotSound()
             } catch (e: IllegalStateException) {
@@ -58,12 +58,10 @@
         }
 
     override fun playCameraSound(): Deferred<Unit> {
-        return coroutineScope.tracedAsync("playCameraSound", bgDispatcher) {
-            player.await()?.start()
-        }
+        return coroutineScope.async("playCameraSound", bgDispatcher) { player.await()?.start() }
     }
     override fun releaseScreenshotSound(): Deferred<Unit> {
-        return coroutineScope.tracedAsync("releaseScreenshotSound", bgDispatcher) {
+        return coroutineScope.async("releaseScreenshotSound", bgDispatcher) {
             try {
                 withTimeout(1.seconds) { player.await()?.release() }
             } catch (e: TimeoutCancellationException) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
index 0158284..5684605 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
@@ -13,14 +13,11 @@
 import com.android.systemui.res.R
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED
 import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
+import com.android.systemui.util.TraceUtils.Companion.launch
 import java.util.function.Consumer
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.flow.first
 
 /**
  * Receives the signal to take a screenshot from [TakeScreenshotService], and calls back with the
@@ -40,12 +37,7 @@
     private val screenshotNotificationControllerFactory: ScreenshotNotificationsController.Factory,
 ) {
 
-    private lateinit var displays: StateFlow<Set<Display>>
-    private val displaysCollectionJob: Job =
-        mainScope.launch {
-            displays = displayRepository.displays.stateIn(this, SharingStarted.Eagerly, emptySet())
-        }
-
+    private val displays = displayRepository.displays
     private val screenshotControllers = mutableMapOf<Int, ScreenshotController>()
     private val notificationControllers = mutableMapOf<Int, ScreenshotNotificationsController>()
 
@@ -63,6 +55,7 @@
         val displayIds = getDisplaysToScreenshot(screenshotRequest.type)
         val resultCallbackWrapper = MultiResultCallbackWrapper(requestCallback)
         displayIds.forEach { displayId: Int ->
+            Log.d(TAG, "Executing screenshot for display $displayId")
             dispatchToController(
                 rawScreenshotData = ScreenshotData.fromRequest(screenshotRequest, displayId),
                 onSaved =
@@ -126,12 +119,12 @@
         callback.reportError()
     }
 
-    private fun getDisplaysToScreenshot(requestType: Int): List<Int> {
+    private suspend fun getDisplaysToScreenshot(requestType: Int): List<Int> {
         return if (requestType == TAKE_SCREENSHOT_PROVIDED_IMAGE) {
             // If this is a provided image, let's show the UI on the default display only.
             listOf(Display.DEFAULT_DISPLAY)
         } else {
-            displays.value.filter { it.type in ALLOWED_DISPLAY_TYPES }.map { it.displayId }
+            displays.first().filter { it.type in ALLOWED_DISPLAY_TYPES }.map { it.displayId }
         }
     }
 
@@ -163,7 +156,6 @@
             screenshotController.onDestroy()
         }
         screenshotControllers.clear()
-        displaysCollectionJob.cancel()
     }
 
     private fun getScreenshotController(id: Int): ScreenshotController {
@@ -184,7 +176,7 @@
         onSaved: Consumer<Uri>,
         requestCallback: RequestCallback
     ) {
-        mainScope.launch {
+        mainScope.launch("TakeScreenshotService#executeScreenshotsAsync") {
             executeScreenshots(screenshotRequest, { uri -> onSaved.accept(uri) }, requestCallback)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index d869239..3d3447b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -35,7 +35,6 @@
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.Dumpable;
-import com.android.systemui.FeatureFlags;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
@@ -43,6 +42,7 @@
 import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder;
 import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel;
 import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.communal.data.repository.CommunalRepository;
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel;
 import com.android.systemui.compose.ComposeFacade;
 import com.android.systemui.dagger.SysUISingleton;
@@ -107,8 +107,8 @@
     private final LockscreenHostedDreamGestureListener mLockscreenHostedDreamGestureListener;
     private final NotificationInsetsController mNotificationInsetsController;
     private final CommunalViewModel mCommunalViewModel;
+    private final CommunalRepository mCommunalRepository;
     private final boolean mIsTrackpadCommonEnabled;
-    private final FeatureFlags mFeatureFlags;
     private final FeatureFlagsClassic mFeatureFlagsClassic;
     private final SysUIKeyEventHandler mSysUIKeyEventHandler;
     private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@@ -181,9 +181,9 @@
             KeyguardTransitionInteractor keyguardTransitionInteractor,
             PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
             CommunalViewModel communalViewModel,
+            CommunalRepository communalRepository,
             NotificationExpansionRepository notificationExpansionRepository,
             FeatureFlagsClassic featureFlagsClassic,
-            FeatureFlags featureFlags,
             SystemClock clock,
             BouncerMessageInteractor bouncerMessageInteractor,
             BouncerLogger bouncerLogger,
@@ -214,8 +214,8 @@
         mLockscreenHostedDreamGestureListener = lockscreenHostedDreamGestureListener;
         mNotificationInsetsController = notificationInsetsController;
         mCommunalViewModel = communalViewModel;
+        mCommunalRepository = communalRepository;
         mIsTrackpadCommonEnabled = featureFlagsClassic.isEnabled(TRACKPAD_GESTURE_COMMON);
-        mFeatureFlags = featureFlags;
         mFeatureFlagsClassic = featureFlagsClassic;
         mSysUIKeyEventHandler = sysUIKeyEventHandler;
         mPrimaryBouncerInteractor = primaryBouncerInteractor;
@@ -575,7 +575,8 @@
      * The layout lives in {@link R.id.communal_ui_container}.
      */
     public void setupCommunalHubLayout() {
-        if (!mFeatureFlags.communalHub() || !ComposeFacade.INSTANCE.isComposeAvailable()) {
+        if (!mCommunalRepository.isCommunalEnabled()
+                || !ComposeFacade.INSTANCE.isComposeAvailable()) {
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index ff4570e..2e1e395 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -29,8 +29,11 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.dagger.CentralSurfacesModule;
+import com.android.systemui.statusbar.domain.interactor.SilentNotificationStatusIconsVisibilityInteractor;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
 import com.android.systemui.statusbar.notification.collection.PipelineDumper;
@@ -59,7 +62,9 @@
     private static final long MAX_RANKING_DELAY_MILLIS = 500L;
 
     private final Context mContext;
+    private final FeatureFlagsClassic mFeatureFlags;
     private final NotificationManager mNotificationManager;
+    private final SilentNotificationStatusIconsVisibilityInteractor mStatusIconInteractor;
     private final SystemClock mSystemClock;
     private final Executor mMainExecutor;
     private final List<NotificationHandler> mNotificationHandlers = new ArrayList<>();
@@ -75,13 +80,17 @@
     @Inject
     public NotificationListener(
             Context context,
+            FeatureFlagsClassic featureFlags,
             NotificationManager notificationManager,
+            SilentNotificationStatusIconsVisibilityInteractor statusIconInteractor,
             SystemClock systemClock,
             @Main Executor mainExecutor,
             PluginManager pluginManager) {
         super(pluginManager);
         mContext = context;
+        mFeatureFlags = featureFlags;
         mNotificationManager = notificationManager;
+        mStatusIconInteractor = statusIconInteractor;
         mSystemClock = systemClock;
         mMainExecutor = mainExecutor;
     }
@@ -95,6 +104,7 @@
     }
 
     /** Registers a listener that's notified when any notification-related settings change. */
+    @Deprecated
     public void addNotificationSettingsListener(NotificationSettingsListener listener) {
         mSettingsListeners.add(listener);
     }
@@ -230,8 +240,12 @@
 
     @Override
     public void onSilentStatusBarIconsVisibilityChanged(boolean hideSilentStatusIcons) {
-        for (NotificationSettingsListener listener : mSettingsListeners) {
-            listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+        if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+            mStatusIconInteractor.setHideSilentStatusIcons(hideSilentStatusIcons);
+        } else {
+            for (NotificationSettingsListener listener : mSettingsListeners) {
+                listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+            }
         }
     }
 
@@ -294,6 +308,7 @@
         return ranking;
     }
 
+    @Deprecated
     public interface NotificationSettingsListener {
 
         default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index e2de37f..22912df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -17,18 +17,13 @@
 package com.android.systemui.statusbar.dagger
 
 import com.android.systemui.CoreStartable
-import com.android.systemui.statusbar.core.StatusBarInitializer
-import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepository
-import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryImpl
-import com.android.systemui.statusbar.data.repository.StatusBarModeRepository
-import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryImpl
+import com.android.systemui.statusbar.data.StatusBarDataLayerModule
 import com.android.systemui.statusbar.phone.LightBarController
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
-import dagger.multibindings.IntoSet
 
 /**
  * A module for **only** classes related to the status bar **UI element**. This module specifically
@@ -38,24 +33,9 @@
  *   ([com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule],
  *   [com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule], etc.).
  */
-@Module
+@Module(includes = [StatusBarDataLayerModule::class])
 abstract class StatusBarModule {
     @Binds
-    abstract fun bindStatusBarModeRepository(
-        impl: StatusBarModeRepositoryImpl
-    ): StatusBarModeRepository
-
-    @Binds
-    @IntoMap
-    @ClassKey(StatusBarModeRepositoryImpl::class)
-    abstract fun bindStatusBarModeRepositoryStart(impl: StatusBarModeRepositoryImpl): CoreStartable
-
-    @Binds
-    abstract fun bindKeyguardStatusBarRepository(
-        impl: KeyguardStatusBarRepositoryImpl
-    ): KeyguardStatusBarRepository
-
-    @Binds
     @IntoMap
     @ClassKey(OngoingCallController::class)
     abstract fun bindOngoingCallController(impl: OngoingCallController): CoreStartable
@@ -64,10 +44,4 @@
     @IntoMap
     @ClassKey(LightBarController::class)
     abstract fun bindLightBarController(impl: LightBarController): CoreStartable
-
-    @Binds
-    @IntoSet
-    abstract fun statusBarInitializedListener(
-        statusBarModeRepository: StatusBarModeRepository,
-    ): StatusBarInitializer.OnStatusBarViewInitializedListener
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
new file mode 100644
index 0000000..29d53fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.data
+
+import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryModule
+import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryModule
+import com.android.systemui.statusbar.phone.data.StatusBarPhoneDataLayerModule
+import dagger.Module
+
+@Module(
+    includes =
+        [
+            KeyguardStatusBarRepositoryModule::class,
+            StatusBarModeRepositoryModule::class,
+            StatusBarPhoneDataLayerModule::class
+        ]
+)
+object StatusBarDataLayerModule
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
index 8136de9..d1594ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.user.data.repository.UserSwitcherRepository
+import dagger.Binds
+import dagger.Module
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
@@ -78,3 +80,8 @@
             isEnabled && isKeyguardEnabled
         }
 }
+
+@Module
+interface KeyguardStatusBarRepositoryModule {
+    @Binds fun bindImpl(impl: KeyguardStatusBarRepositoryImpl): KeyguardStatusBarRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/NotificationListenerSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/NotificationListenerSettingsRepository.kt
new file mode 100644
index 0000000..2c706a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/NotificationListenerSettingsRepository.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.NotificationListener
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+
+/** Exposes state pertaining to settings tracked over the [NotificationListener] boundary. */
+@SysUISingleton
+class NotificationListenerSettingsRepository @Inject constructor() {
+    /** Should icons for silent notifications be shown in the status bar? */
+    val showSilentStatusIcons = MutableStateFlow(true)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt
index 2b05994..47994d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt
@@ -30,7 +30,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.DisplayId
 import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.core.StatusBarInitializer
+import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener
 import com.android.systemui.statusbar.data.model.StatusBarAppearance
 import com.android.systemui.statusbar.data.model.StatusBarMode
 import com.android.systemui.statusbar.phone.BoundsPair
@@ -38,6 +38,11 @@
 import com.android.systemui.statusbar.phone.StatusBarBoundsProvider
 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
 import com.android.systemui.statusbar.phone.ongoingcall.data.repository.OngoingCallRepository
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import dagger.multibindings.IntoSet
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -56,7 +61,7 @@
  * Note: These status bar modes are status bar *window* states that are sent to us from
  * WindowManager, not determined internally.
  */
-interface StatusBarModeRepository : StatusBarInitializer.OnStatusBarViewInitializedListener {
+interface StatusBarModeRepository {
     /**
      * True if the status bar window is showing transiently and will disappear soon, and false
      * otherwise. ("Otherwise" in this case means the status bar is persistently hidden OR
@@ -112,7 +117,7 @@
     private val commandQueue: CommandQueue,
     private val letterboxAppearanceCalculator: LetterboxAppearanceCalculator,
     ongoingCallRepository: OngoingCallRepository,
-) : StatusBarModeRepository, CoreStartable {
+) : StatusBarModeRepository, CoreStartable, OnStatusBarViewInitializedListener {
 
     private val commandQueueCallback =
         object : CommandQueue.Callbacks {
@@ -334,3 +339,17 @@
         val statusBarBounds: BoundsPair,
     )
 }
+
+@Module
+interface StatusBarModeRepositoryModule {
+    @Binds fun bindImpl(impl: StatusBarModeRepositoryImpl): StatusBarModeRepository
+
+    @Binds
+    @IntoMap
+    @ClassKey(StatusBarModeRepositoryImpl::class)
+    fun bindCoreStartable(impl: StatusBarModeRepositoryImpl): CoreStartable
+
+    @Binds
+    @IntoSet
+    fun bindViewInitListener(impl: StatusBarModeRepositoryImpl): OnStatusBarViewInitializedListener
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/SilentNotificationStatusIconsVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/SilentNotificationStatusIconsVisibilityInteractor.kt
new file mode 100644
index 0000000..1248b1c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/SilentNotificationStatusIconsVisibilityInteractor.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.domain.interactor
+
+import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository
+import javax.inject.Inject
+
+class SilentNotificationStatusIconsVisibilityInteractor
+@Inject
+constructor(private val repository: NotificationListenerSettingsRepository) {
+    /** Set whether icons for silent notifications be hidden in the status bar. */
+    fun setHideSilentStatusIcons(hideIcons: Boolean) {
+        repository.showSilentStatusIcons.value = !hideIcons
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
index 8957f29..f98f39e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
+import android.util.Log;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -33,6 +34,7 @@
  * An animator to animate properties
  */
 public class PropertyAnimator {
+    private static final String TAG = "PropertyAnimator";
 
     /**
      * Set a property on a view, updating its value, even if it's already animating.
@@ -123,6 +125,8 @@
                     view.setTag(animatorTag, null);
                     view.setTag(animationStartTag, null);
                     view.setTag(animationEndTag, null);
+                } else {
+                    Log.e(TAG, "Unexpected Animator set during onAnimationEnd. Not cleaning up.");
                 }
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index e763797..7b3a93a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -225,7 +225,7 @@
 
     /** @see NotifPipeline#getEntry(String) () */
     @Nullable
-    NotificationEntry getEntry(@NonNull String key) {
+    public NotificationEntry getEntry(@NonNull String key) {
         return mNotificationSet.get(key);
     }
 
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
index 2d83970..0c69a65 100644
--- 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
@@ -37,8 +37,8 @@
 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.domain.interactor.SeenNotificationsInteractor
 import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.headsUpEvents
 import com.android.systemui.util.asIndenting
@@ -85,7 +85,7 @@
     @Application private val scope: CoroutineScope,
     private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
     private val secureSettings: SecureSettings,
-    private val notificationListInteractor: NotificationListInteractor,
+    private val seenNotificationsInteractor: SeenNotificationsInteractor,
     private val statusBarStateController: StatusBarStateController,
 ) : Coordinator, Dumpable {
 
@@ -351,7 +351,7 @@
 
             override fun onCleanup() {
                 logger.logProviderHasFilteredOutSeenNotifs(hasFilteredAnyNotifs)
-                notificationListInteractor.setHasFilteredOutSeenNotifications(hasFilteredAnyNotifs)
+                seenNotificationsInteractor.setHasFilteredOutSeenNotifications(hasFilteredAnyNotifs)
                 hasFilteredAnyNotifs = false
             }
         }
@@ -389,7 +389,7 @@
         with(pw.asIndenting()) {
             println(
                 "notificationListInteractor.hasFilteredOutSeenNotifications.value=" +
-                    notificationListInteractor.hasFilteredOutSeenNotifications.value
+                    seenNotificationsInteractor.hasFilteredOutSeenNotifications.value
             )
             println("unseen notifications:")
             indentIfPossible {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 62a0d13..07e84bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -16,25 +16,32 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator
 
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.notification.collection.ListEntry
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.util.traceSection
 import javax.inject.Inject
 
 /**
- * A small coordinator which updates the notif stack (the view layer which holds notifications)
- * with high-level data after the stack is populated with the final entries.
+ * A small coordinator which updates the notif stack (the view layer which holds notifications) with
+ * high-level data after the stack is populated with the final entries.
  */
 @CoordinatorScope
-class StackCoordinator @Inject internal constructor(
+class StackCoordinator
+@Inject
+internal constructor(
+    private val featureFlags: FeatureFlagsClassic,
     private val groupExpansionManagerImpl: GroupExpansionManagerImpl,
-    private val notificationIconAreaController: NotificationIconAreaController
+    private val notificationIconAreaController: NotificationIconAreaController,
+    private val renderListInteractor: RenderNotificationListInteractor,
 ) : Coordinator {
 
     override fun attach(pipeline: NotifPipeline) {
@@ -45,7 +52,11 @@
     fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) =
         traceSection("StackCoordinator.onAfterRenderList") {
             controller.setNotifStats(calculateNotifStats(entries))
-            notificationIconAreaController.updateNotificationIcons(entries)
+            if (featureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+                renderListInteractor.setRenderedList(entries)
+            } else {
+                notificationIconAreaController.updateNotificationIcons(entries)
+            }
         }
 
     private fun calculateNotifStats(entries: List<ListEntry>): NotifStats {
@@ -75,4 +86,4 @@
             hasClearableSilentNotifs = hasClearableSilentNotifs
         )
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
new file mode 100644
index 0000000..8064f04
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+
+/**
+ * Repository of "active" notifications in the notification list.
+ *
+ * This repository serves as the boundary between the
+ * [com.android.systemui.statusbar.notification.collection.NotifPipeline] and the modern
+ * notifications presentation codebase.
+ */
+@SysUISingleton
+class ActiveNotificationListRepository @Inject constructor() {
+    /**
+     * Notifications actively presented to the user in the notification stack.
+     *
+     * @see com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+     */
+    val activeNotifications = MutableStateFlow(emptyMap<String, ActiveNotificationModel>())
+
+    /** Are any already-seen notifications currently filtered out of the active list? */
+    val hasFilteredOutSeenNotifications = MutableStateFlow(false)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
new file mode 100644
index 0000000..bfec60bc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.domain.interactor
+
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+class ActiveNotificationsInteractor
+@Inject
+constructor(
+    repository: ActiveNotificationListRepository,
+) {
+    /** Notifications actively presented to the user in the notification stack, in order. */
+    val notifications: Flow<Collection<ActiveNotificationModel>> =
+        repository.activeNotifications.map { it.values }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractor.kt
similarity index 82%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractor.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractor.kt
index 8f7e269..8079ce5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractor.kt
@@ -20,15 +20,14 @@
 import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
 import javax.inject.Inject
 
-/** Interactor for notifications in general. */
+/** Interactor for notification alerting. */
 @SysUISingleton
-class NotificationsInteractor
+class NotificationAlertsInteractor
 @Inject
 constructor(
     private val disableFlagsRepository: DisableFlagsRepository,
 ) {
     /** Returns true if notification alerts are allowed. */
-    fun areNotificationAlertsEnabled(): Boolean {
-        return disableFlagsRepository.disableFlags.value.areNotificationAlertsEnabled()
-    }
+    fun areNotificationAlertsEnabled(): Boolean =
+        disableFlagsRepository.disableFlags.value.areNotificationAlertsEnabled()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
new file mode 100644
index 0000000..604ecbc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.domain.interactor
+
+import android.graphics.drawable.Icon
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.update
+
+private typealias ModelStore = Map<String, ActiveNotificationModel>
+
+/**
+ * Logic for passing information from the
+ * [com.android.systemui.statusbar.notification.collection.NotifPipeline] to the presentation
+ * layers.
+ */
+class RenderNotificationListInteractor
+@Inject
+constructor(
+    private val repository: ActiveNotificationListRepository,
+    private val sectionStyleProvider: SectionStyleProvider,
+) {
+    /**
+     * Sets the current list of rendered notification entries as displayed in the notification
+     * stack.
+     *
+     * @see com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository.activeNotifications
+     */
+    fun setRenderedList(entries: List<ListEntry>) {
+        repository.activeNotifications.update { existingModels ->
+            entries.associateBy(
+                keySelector = { it.key },
+                valueTransform = { it.toModel(existingModels) },
+            )
+        }
+    }
+
+    private fun ListEntry.toModel(
+        existingModels: ModelStore,
+    ): ActiveNotificationModel =
+        existingModels.createOrReuse(
+            key = key,
+            groupKey = representativeEntry?.sbn?.groupKey,
+            isAmbient = sectionStyleProvider.isMinimized(this),
+            isRowDismissed = representativeEntry?.isRowDismissed == true,
+            isSilent = sectionStyleProvider.isSilent(this),
+            isLastMessageFromReply = representativeEntry?.isLastMessageFromReply == true,
+            isSuppressedFromStatusBar = representativeEntry?.shouldSuppressStatusBar() == true,
+            isPulsing = representativeEntry?.showingPulsing() == true,
+            aodIcon = representativeEntry?.icons?.aodIcon?.sourceIcon,
+            shelfIcon = representativeEntry?.icons?.shelfIcon?.sourceIcon,
+            statusBarIcon = representativeEntry?.icons?.statusBarIcon?.sourceIcon,
+        )
+
+    private fun ModelStore.createOrReuse(
+        key: String,
+        groupKey: String?,
+        isAmbient: Boolean,
+        isRowDismissed: Boolean,
+        isSilent: Boolean,
+        isLastMessageFromReply: Boolean,
+        isSuppressedFromStatusBar: Boolean,
+        isPulsing: Boolean,
+        aodIcon: Icon?,
+        shelfIcon: Icon?,
+        statusBarIcon: Icon?
+    ): ActiveNotificationModel {
+        return this[key]?.takeIf {
+            it.isCurrent(
+                key = key,
+                groupKey = groupKey,
+                isAmbient = isAmbient,
+                isRowDismissed = isRowDismissed,
+                isSilent = isSilent,
+                isLastMessageFromReply = isLastMessageFromReply,
+                isSuppressedFromStatusBar = isSuppressedFromStatusBar,
+                isPulsing = isPulsing,
+                aodIcon = aodIcon,
+                shelfIcon = shelfIcon,
+                statusBarIcon = statusBarIcon
+            )
+        }
+            ?: ActiveNotificationModel(
+                key = key,
+                groupKey = groupKey,
+                isAmbient = isAmbient,
+                isRowDismissed = isRowDismissed,
+                isSilent = isSilent,
+                isLastMessageFromReply = isLastMessageFromReply,
+                isSuppressedFromStatusBar = isSuppressedFromStatusBar,
+                isPulsing = isPulsing,
+                aodIcon = aodIcon,
+                shelfIcon = shelfIcon,
+                statusBarIcon = statusBarIcon,
+            )
+    }
+
+    private fun ActiveNotificationModel.isCurrent(
+        key: String,
+        groupKey: String?,
+        isAmbient: Boolean,
+        isRowDismissed: Boolean,
+        isSilent: Boolean,
+        isLastMessageFromReply: Boolean,
+        isSuppressedFromStatusBar: Boolean,
+        isPulsing: Boolean,
+        aodIcon: Icon?,
+        shelfIcon: Icon?,
+        statusBarIcon: Icon?
+    ): Boolean {
+        return when {
+            key != this.key -> false
+            groupKey != this.groupKey -> false
+            isAmbient != this.isAmbient -> false
+            isRowDismissed != this.isRowDismissed -> false
+            isSilent != this.isSilent -> false
+            isLastMessageFromReply != this.isLastMessageFromReply -> false
+            isSuppressedFromStatusBar != this.isSuppressedFromStatusBar -> false
+            isPulsing != this.isPulsing -> false
+            aodIcon != this.aodIcon -> false
+            shelfIcon != this.shelfIcon -> false
+            statusBarIcon != this.statusBarIcon -> false
+            else -> true
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
similarity index 63%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
index 3fd68a8..1f7ab96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractor.kt
@@ -14,25 +14,26 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.stack.domain.interactor
+package com.android.systemui.statusbar.notification.domain.interactor
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
 import javax.inject.Inject
 import kotlinx.coroutines.flow.StateFlow
 
 /** Interactor for business logic associated with the notification stack. */
 @SysUISingleton
-class NotificationListInteractor
+class SeenNotificationsInteractor
 @Inject
 constructor(
-    private val notificationListRepository: NotificationListRepository,
+    private val notificationListRepository: ActiveNotificationListRepository,
 ) {
     /** Are any already-seen notifications currently filtered out of the shade? */
-    val hasFilteredOutSeenNotifications: StateFlow<Boolean>
-        get() = notificationListRepository.hasFilteredOutSeenNotifications
+    val hasFilteredOutSeenNotifications: StateFlow<Boolean> =
+        notificationListRepository.hasFilteredOutSeenNotifications
 
+    /** Set whether already-seen notifications are currently filtered out of the shade. */
     fun setHasFilteredOutSeenNotifications(value: Boolean) {
-        notificationListRepository.setHasFilteredOutSeenNotifications(value)
+        notificationListRepository.hasFilteredOutSeenNotifications.value = value
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt
new file mode 100644
index 0000000..94e70e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.footer.shared
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the FooterView refactor flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object FooterViewRefactor {
+    const val FLAG_NAME = Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR
+
+    /** Is the refactor enabled */
+    @JvmStatic
+    inline val isEnabled
+        get() = Flags.notificationsFooterViewRefactor()
+
+    /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun isUnexpectedlyInLegacyMode() =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+    /**
+     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+     * the flag is enabled to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
index e74b3fc..ba91654 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
@@ -19,6 +19,9 @@
 import static android.graphics.PorterDuff.Mode.SRC_ATOP;
 
 import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
@@ -35,6 +38,7 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.res.R;
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
 import com.android.systemui.statusbar.notification.row.FooterViewButton;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -44,6 +48,8 @@
 import java.io.PrintWriter;
 
 public class FooterView extends StackScrollerDecorView {
+    private static final String TAG = "FooterView";
+
     private FooterViewButton mClearAllButton;
     private FooterViewButton mManageButton;
     private boolean mShowHistory;
@@ -57,6 +63,9 @@
     private String mSeenNotifsFilteredText;
     private Drawable mSeenNotifsFilteredIcon;
 
+    private @StringRes int mMessageStringId;
+    private @DrawableRes int mMessageIconId;
+
     public FooterView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -84,6 +93,50 @@
         });
     }
 
+    /** Set the string for a message to be shown instead of the buttons. */
+    public void setMessageString(@StringRes int messageId) {
+        if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
+        if (mMessageStringId == messageId) {
+            return; // nothing changed
+        }
+        mMessageStringId = messageId;
+        updateMessageString();
+    }
+
+    private void updateMessageString() {
+        if (mMessageStringId == 0) {
+            return; // not initialized yet
+        }
+        String messageString = getContext().getString(mMessageStringId);
+        mSeenNotifsFooterTextView.setText(messageString);
+    }
+
+
+    /** Set the icon to be shown before the message (see {@link #setMessageString(int)}). */
+    public void setMessageIcon(@DrawableRes int iconId) {
+        if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
+        if (mMessageIconId == iconId) {
+            return; // nothing changed
+        }
+        mMessageIconId = iconId;
+        updateMessageIcon();
+    }
+
+    private void updateMessageIcon() {
+        if (mMessageIconId == 0) {
+            return; // not initialized yet
+        }
+        int unlockIconSize = getResources()
+                .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
+        @SuppressLint("UseCompatLoadingForDrawables")
+        Drawable messageIcon = getContext().getDrawable(mMessageIconId);
+        if (messageIcon != null) {
+            messageIcon.setBounds(0, 0, unlockIconSize, unlockIconSize);
+            mSeenNotifsFooterTextView
+                    .setCompoundDrawablesRelative(messageIcon, null, null, null);
+        }
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -148,9 +201,11 @@
             mManageButton.setText(mManageNotificationText);
             mManageButton.setContentDescription(mManageNotificationText);
         }
-        mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText);
-        mSeenNotifsFooterTextView
-                .setCompoundDrawablesRelative(mSeenNotifsFilteredIcon, null, null, null);
+        if (!FooterViewRefactor.isEnabled()) {
+            mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText);
+            mSeenNotifsFooterTextView
+                    .setCompoundDrawablesRelative(mSeenNotifsFilteredIcon, null, null, null);
+        }
     }
 
     /** Whether the start button shows "History" (true) or "Manage" (false). */
@@ -167,6 +222,11 @@
                 mContext.getString(R.string.accessibility_clear_all));
         updateResources();
         updateContent();
+
+        if (FooterViewRefactor.isEnabled()) {
+            updateMessageString();
+            updateMessageIcon();
+        }
     }
 
     /**
@@ -200,11 +260,13 @@
         mManageNotificationText = getContext().getString(R.string.manage_notifications_text);
         mManageNotificationHistoryText = getContext()
                 .getString(R.string.manage_notifications_history_text);
-        int unlockIconSize = getResources()
-                .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
-        mSeenNotifsFilteredText = getContext().getString(R.string.unlock_to_see_notif_text);
-        mSeenNotifsFilteredIcon = getContext().getDrawable(R.drawable.ic_friction_lock_closed);
-        mSeenNotifsFilteredIcon.setBounds(0, 0, unlockIconSize, unlockIconSize);
+        if (!FooterViewRefactor.isEnabled()) {
+            int unlockIconSize = getResources()
+                    .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
+            mSeenNotifsFilteredText = getContext().getString(R.string.unlock_to_see_notif_text);
+            mSeenNotifsFilteredIcon = getContext().getDrawable(R.drawable.ic_friction_lock_closed);
+            mSeenNotifsFilteredIcon.setBounds(0, 0, unlockIconSize, unlockIconSize);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt
new file mode 100644
index 0000000..6d823437
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewbinder/FooterViewBinder.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.footer.ui.viewbinder
+
+import androidx.lifecycle.lifecycleScope
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
+import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModel
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.launch
+
+/** Binds a [FooterView] to its [view model][FooterViewModel]. */
+object FooterViewBinder {
+    fun bind(
+        footer: FooterView,
+        viewModel: FooterViewModel,
+    ): DisposableHandle {
+        return footer.repeatWhenAttached {
+            // Listen for changes when the view is attached.
+            lifecycleScope.launch {
+                viewModel.message.collect { message ->
+                    footer.setFooterLabelVisible(message.visible)
+                    footer.setMessageString(message.messageId)
+                    footer.setMessageIcon(message.iconId)
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterMessageViewModel.kt
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterMessageViewModel.kt
index 9b0c3fa..bc912fb 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterMessageViewModel.kt
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.systemui.common.ui.data.repository
+package com.android.systemui.statusbar.notification.footer.ui.viewmodel
 
-import dagger.Binds
-import dagger.Module
+import android.annotation.DrawableRes
+import android.annotation.StringRes
 
-@Module
-interface CommonRepositoryModule {
-    @Binds fun bindRepository(impl: ConfigurationRepositoryImpl): ConfigurationRepository
-}
+/** A ViewModel for the string message that can be shown in the footer. */
+data class FooterMessageViewModel(
+    @StringRes val messageId: Int,
+    @DrawableRes val iconId: Int,
+    val visible: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
new file mode 100644
index 0000000..ffa5ff0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.footer.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
+import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** ViewModel for [FooterView]. */
+@SysUISingleton
+class FooterViewModel
+@Inject
+constructor(seenNotificationsInteractor: SeenNotificationsInteractor) {
+    init {
+        /* Check if */ FooterViewRefactor.isUnexpectedlyInLegacyMode()
+    }
+
+    val message: Flow<FooterMessageViewModel> =
+        seenNotificationsInteractor.hasFilteredOutSeenNotifications.map { hasFilteredOutNotifs ->
+            FooterMessageViewModel(
+                messageId = R.string.unlock_to_see_notif_text,
+                iconId = R.drawable.ic_friction_lock_closed,
+                visible = hasFilteredOutNotifs,
+            )
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
new file mode 100644
index 0000000..00d873e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.notification.icon.domain.interactor
+
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository
+import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.wm.shell.bubbles.Bubbles
+import java.util.Optional
+import javax.inject.Inject
+import kotlin.jvm.optionals.getOrNull
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flatMapLatest
+
+/** Domain logic related to notification icons. */
+class NotificationIconsInteractor
+@Inject
+constructor(
+    private val activeNotificationsInteractor: ActiveNotificationsInteractor,
+    private val bubbles: Optional<Bubbles>,
+    private val keyguardViewStateRepository: NotificationsKeyguardViewStateRepository,
+) {
+    /** Returns a subset of all active notifications based on the supplied filtration parameters. */
+    fun filteredNotifSet(
+        showAmbient: Boolean = true,
+        showLowPriority: Boolean = true,
+        showDismissed: Boolean = true,
+        showRepliedMessages: Boolean = true,
+        showPulsing: Boolean = true,
+    ): Flow<Set<ActiveNotificationModel>> {
+        return combine(
+            activeNotificationsInteractor.notifications,
+            keyguardViewStateRepository.areNotificationsFullyHidden,
+        ) { notifications, notifsFullyHidden ->
+            notifications
+                .asSequence()
+                .filter { model: ActiveNotificationModel ->
+                    shouldShowNotificationIcon(
+                        model = model,
+                        showAmbient = showAmbient,
+                        showLowPriority = showLowPriority,
+                        showDismissed = showDismissed,
+                        showRepliedMessages = showRepliedMessages,
+                        showPulsing = showPulsing,
+                        notifsFullyHidden = notifsFullyHidden,
+                    )
+                }
+                .toSet()
+        }
+    }
+
+    private fun shouldShowNotificationIcon(
+        model: ActiveNotificationModel,
+        showAmbient: Boolean,
+        showLowPriority: Boolean,
+        showDismissed: Boolean,
+        showRepliedMessages: Boolean,
+        showPulsing: Boolean,
+        notifsFullyHidden: Boolean,
+    ): Boolean {
+        return when {
+            !showAmbient && model.isAmbient -> false
+            !showLowPriority && model.isSilent -> false
+            !showDismissed && model.isRowDismissed -> false
+            !showRepliedMessages && model.isLastMessageFromReply -> false
+            !showAmbient && model.isSuppressedFromStatusBar -> false
+            !showPulsing && model.isPulsing && !notifsFullyHidden -> false
+            bubbles.getOrNull()?.isBubbleExpanded(model.key) == true -> false
+            else -> true
+        }
+    }
+}
+
+/** Domain logic related to notification icons shown on the always-on display. */
+class AlwaysOnDisplayNotificationIconsInteractor
+@Inject
+constructor(
+    deviceEntryInteractor: DeviceEntryInteractor,
+    iconsInteractor: NotificationIconsInteractor,
+) {
+    val aodNotifs: Flow<Set<ActiveNotificationModel>> =
+        deviceEntryInteractor.isBypassEnabled.flatMapLatest { isBypassEnabled ->
+            iconsInteractor.filteredNotifSet(
+                showAmbient = false,
+                showDismissed = false,
+                showRepliedMessages = false,
+                showPulsing = !isBypassEnabled,
+            )
+        }
+}
+
+/** Domain logic related to notification icons shown in the status bar. */
+class StatusBarNotificationIconsInteractor
+@Inject
+constructor(
+    iconsInteractor: NotificationIconsInteractor,
+    settingsRepository: NotificationListenerSettingsRepository,
+) {
+    val statusBarNotifs: Flow<Set<ActiveNotificationModel>> =
+        settingsRepository.showSilentStatusIcons.flatMapLatest { showSilentIcons ->
+            iconsInteractor.filteredNotifSet(
+                showAmbient = false,
+                showLowPriority = showSilentIcons,
+                showDismissed = false,
+                showRepliedMessages = false,
+            )
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
index eb5c1fa..d8a5f01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
@@ -16,50 +16,30 @@
 package com.android.systemui.statusbar.notification.icon.ui.viewbinder
 
 import android.content.Context
-import android.graphics.Color
 import android.graphics.Rect
 import android.os.Bundle
-import android.os.Trace
 import android.view.LayoutInflater
 import android.view.View
-import android.widget.FrameLayout
-import androidx.annotation.ColorInt
-import androidx.annotation.VisibleForTesting
-import androidx.collection.ArrayMap
-import com.android.internal.statusbar.StatusBarIcon
-import com.android.internal.util.ContrastColorUtil
-import com.android.settingslib.Utils
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.RefactorFlag
-import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.NotificationListener
-import com.android.systemui.statusbar.NotificationMediaManager
 import com.android.systemui.statusbar.NotificationShelfController
 import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.notification.NotificationUtils
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
 import com.android.systemui.statusbar.notification.collection.ListEntry
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerShelfViewModel
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerStatusBarViewModel
 import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl
 import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.phone.NotificationIconContainer
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.window.StatusBarWindowController
-import com.android.wm.shell.bubbles.Bubbles
-import java.util.Optional
-import java.util.function.Function
 import javax.inject.Inject
 import kotlinx.coroutines.DisposableHandle
 
@@ -74,68 +54,32 @@
 class NotificationIconAreaControllerViewBinderWrapperImpl
 @Inject
 constructor(
-    private val context: Context,
-    private val wakeUpCoordinator: NotificationWakeUpCoordinator,
-    private val bypassController: KeyguardBypassController,
+    context: Context,
+    private val configuration: ConfigurationState,
     private val configurationController: ConfigurationController,
-    private val mediaManager: NotificationMediaManager,
-    notificationListener: NotificationListener,
     private val dozeParameters: DozeParameters,
-    private val sectionStyleProvider: SectionStyleProvider,
-    private val bubblesOptional: Optional<Bubbles>,
     demoModeController: DemoModeController,
-    darkIconDispatcher: DarkIconDispatcher,
     private val featureFlags: FeatureFlagsClassic,
-    private val statusBarWindowController: StatusBarWindowController,
     private val screenOffAnimationController: ScreenOffAnimationController,
+    private val shelfIconViewStore: ShelfNotificationIconViewStore,
     private val shelfIconsViewModel: NotificationIconContainerShelfViewModel,
-    private val statusBarIconsViewModel: NotificationIconContainerStatusBarViewModel,
+    private val aodIconViewStore: AlwaysOnDisplayNotificationIconViewStore,
     private val aodIconsViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
-) :
-    NotificationIconAreaController,
-    DarkIconDispatcher.DarkReceiver,
-    NotificationWakeUpCoordinator.WakeUpListener,
-    DemoMode {
+    private val statusBarIconViewStore: StatusBarNotificationIconViewStore,
+    private val statusBarIconsViewModel: NotificationIconContainerStatusBarViewModel,
+) : NotificationIconAreaController, DemoMode {
 
-    private val contrastColorUtil: ContrastColorUtil = ContrastColorUtil.getInstance(context)
-    private val updateStatusBarIcons = Runnable { updateStatusBarIcons() }
     private val shelfRefactor = RefactorFlag(featureFlags, Flags.NOTIFICATION_SHELF_REFACTOR)
-    private val tintAreas = ArrayList<Rect>()
 
-    private var iconSize = 0
-    private var iconHPadding = 0
-    private var iconTint = Color.WHITE
-    private var notificationEntries = listOf<ListEntry>()
     private var notificationIconArea: View? = null
     private var notificationIcons: NotificationIconContainer? = null
     private var shelfIcons: NotificationIconContainer? = null
     private var aodIcons: NotificationIconContainer? = null
     private var aodBindJob: DisposableHandle? = null
-    private var aodIconAppearTranslation = 0
-    private var aodIconTint = 0
-    private var showLowPriority = true
-
-    @VisibleForTesting
-    val settingsListener: NotificationListener.NotificationSettingsListener =
-        object : NotificationListener.NotificationSettingsListener {
-            override fun onStatusBarIconsBehaviorChanged(hideSilentStatusIcons: Boolean) {
-                showLowPriority = !hideSilentStatusIcons
-                updateStatusBarIcons()
-            }
-        }
 
     init {
-        wakeUpCoordinator.addListener(this)
         demoModeController.addCallback(this)
-        notificationListener.addNotificationSettingsListener(settingsListener)
         initializeNotificationAreaViews(context)
-        reloadAodColor()
-        darkIconDispatcher.addDarkReceiver(this)
-    }
-
-    @VisibleForTesting
-    fun shouldShowLowPriorityIcons(): Boolean {
-        return showLowPriority
     }
 
     /** Called by the Keyguard*ViewController whose view contains the aod icons. */
@@ -152,92 +96,45 @@
             NotificationIconContainerViewBinder.bind(
                 aodIcons,
                 aodIconsViewModel,
+                configuration,
                 configurationController,
                 dozeParameters,
                 featureFlags,
                 screenOffAnimationController,
+                aodIconViewStore,
             )
-        if (changed) {
-            updateAodNotificationIcons()
-        }
-        updateIconLayoutParams(context)
     }
 
     override fun setupShelf(notificationShelfController: NotificationShelfController) =
         NotificationShelfViewBinderWrapperControllerImpl.unsupported
 
     override fun setShelfIcons(icons: NotificationIconContainer) {
-        if (shelfRefactor.isUnexpectedlyInLegacyMode()) return
-        NotificationIconContainerViewBinder.bind(
-            icons,
-            shelfIconsViewModel,
-            configurationController,
-            dozeParameters,
-            featureFlags,
-            screenOffAnimationController,
-        )
-        shelfIcons = icons
+        if (shelfRefactor.isUnexpectedlyInLegacyMode()) {
+            NotificationIconContainerViewBinder.bind(
+                icons,
+                shelfIconsViewModel,
+                configuration,
+                configurationController,
+                dozeParameters,
+                featureFlags,
+                screenOffAnimationController,
+                shelfIconViewStore,
+            )
+            shelfIcons = icons
+        }
     }
 
-    override fun onDensityOrFontScaleChanged(context: Context) {
-        updateIconLayoutParams(context)
-    }
+    override fun onDensityOrFontScaleChanged(context: Context) = unsupported
 
     /** Returns the view that represents the notification area. */
     override fun getNotificationInnerAreaView(): View? {
         return notificationIconArea
     }
 
-    /**
-     * See [com.android.systemui.statusbar.policy.DarkIconDispatcher.setIconsDarkArea]. Sets the
-     * color that should be used to tint any icons in the notification area.
-     *
-     * @param tintAreas the areas in which to tint the icons, specified in screen coordinates
-     * @param darkIntensity
-     */
-    override fun onDarkChanged(tintAreas: ArrayList<Rect>, darkIntensity: Float, iconTint: Int) {
-        this.tintAreas.clear()
-        this.tintAreas.addAll(tintAreas)
-        if (DarkIconDispatcher.isInAreas(tintAreas, notificationIconArea)) {
-            this.iconTint = iconTint
-        }
-        applyNotificationIconsTint()
-    }
-
     /** Updates the notifications with the given list of notifications to display. */
-    override fun updateNotificationIcons(entries: List<ListEntry>) {
-        notificationEntries = entries
-        updateNotificationIcons()
-    }
+    override fun updateNotificationIcons(entries: List<ListEntry>) = unsupported
 
-    private fun updateStatusBarIcons() {
-        updateIconsForLayout(
-            { entry: NotificationEntry -> entry.icons.statusBarIcon },
-            notificationIcons,
-            showAmbient = false /* showAmbient */,
-            showLowPriority = showLowPriority,
-            hideDismissed = true /* hideDismissed */,
-            hideRepliedMessages = true /* hideRepliedMessages */,
-            hideCurrentMedia = false /* hideCurrentMedia */,
-            hidePulsing = false /* hidePulsing */
-        )
-    }
-
-    override fun updateAodNotificationIcons() {
-        if (aodIcons == null) {
-            return
-        }
-        updateIconsForLayout(
-            { entry: NotificationEntry -> entry.icons.aodIcon },
-            aodIcons,
-            showAmbient = false /* showAmbient */,
-            showLowPriority = true /* showLowPriority */,
-            hideDismissed = true /* hideDismissed */,
-            hideRepliedMessages = true /* hideRepliedMessages */,
-            hideCurrentMedia = true /* hideCurrentMedia */,
-            hidePulsing = bypassController.bypassEnabled /* hidePulsing */
-        )
-    }
+    override fun updateAodNotificationIcons() = unsupported
 
     override fun showIconIsolated(icon: StatusBarIconView?, animated: Boolean) {
         notificationIcons!!.showIconIsolated(icon, animated)
@@ -249,20 +146,12 @@
 
     override fun setAnimationsEnabled(enabled: Boolean) = unsupported
 
-    override fun onThemeChanged() {
-        reloadAodColor()
-        updateAodIconColors()
-    }
+    override fun onThemeChanged() = unsupported
 
     override fun getHeight(): Int {
         return if (aodIcons == null) 0 else aodIcons!!.height
     }
 
-    override fun onFullyHiddenChanged(isFullyHidden: Boolean) {
-        updateAodNotificationIcons()
-        updateAodIconColors()
-    }
-
     override fun demoCommands(): List<String> {
         val commands = ArrayList<String>()
         commands.add(DemoMode.COMMAND_NOTIFICATIONS)
@@ -289,292 +178,22 @@
 
     /** Initializes the views that will represent the notification area. */
     private fun initializeNotificationAreaViews(context: Context) {
-        reloadDimens(context)
         val layoutInflater = LayoutInflater.from(context)
         notificationIconArea = inflateIconArea(layoutInflater)
         notificationIcons = notificationIconArea?.findViewById(R.id.notificationIcons)
         NotificationIconContainerViewBinder.bind(
             notificationIcons!!,
             statusBarIconsViewModel,
+            configuration,
             configurationController,
             dozeParameters,
             featureFlags,
             screenOffAnimationController,
+            statusBarIconViewStore,
         )
     }
 
-    private fun updateIconLayoutParams(context: Context) {
-        reloadDimens(context)
-        val params = generateIconLayoutParams()
-        for (i in 0 until notificationIcons!!.childCount) {
-            val child = notificationIcons!!.getChildAt(i)
-            child.layoutParams = params
-        }
-        if (shelfIcons != null) {
-            for (i in 0 until shelfIcons!!.childCount) {
-                val child = shelfIcons!!.getChildAt(i)
-                child.layoutParams = params
-            }
-        }
-        if (aodIcons != null) {
-            for (i in 0 until aodIcons!!.childCount) {
-                val child = aodIcons!!.getChildAt(i)
-                child.layoutParams = params
-            }
-        }
-    }
-
-    private fun generateIconLayoutParams(): FrameLayout.LayoutParams {
-        return FrameLayout.LayoutParams(
-            iconSize + 2 * iconHPadding,
-            statusBarWindowController.statusBarHeight
-        )
-    }
-
-    private fun reloadDimens(context: Context) {
-        val res = context.resources
-        iconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size_sp)
-        iconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin)
-        aodIconAppearTranslation = res.getDimensionPixelSize(R.dimen.shelf_appear_translation)
-    }
-
-    private fun shouldShowNotificationIcon(
-        entry: NotificationEntry,
-        showAmbient: Boolean,
-        showLowPriority: Boolean,
-        hideDismissed: Boolean,
-        hideRepliedMessages: Boolean,
-        hideCurrentMedia: Boolean,
-        hidePulsing: Boolean
-    ): Boolean {
-        if (!showAmbient && sectionStyleProvider.isMinimized(entry)) {
-            return false
-        }
-        if (hideCurrentMedia && entry.key == mediaManager.mediaNotificationKey) {
-            return false
-        }
-        if (!showLowPriority && sectionStyleProvider.isSilent(entry)) {
-            return false
-        }
-        if (entry.isRowDismissed && hideDismissed) {
-            return false
-        }
-        if (hideRepliedMessages && entry.isLastMessageFromReply) {
-            return false
-        }
-        // showAmbient == show in shade but not shelf
-        if (!showAmbient && entry.shouldSuppressStatusBar()) {
-            return false
-        }
-        if (
-            hidePulsing &&
-                entry.showingPulsing() &&
-                (!wakeUpCoordinator.notificationsFullyHidden || !entry.isPulseSuppressed)
-        ) {
-            return false
-        }
-        return if (bubblesOptional.isPresent && bubblesOptional.get().isBubbleExpanded(entry.key)) {
-            false
-        } else true
-    }
-
-    private fun updateNotificationIcons() {
-        Trace.beginSection("NotificationIconAreaController.updateNotificationIcons")
-        updateStatusBarIcons()
-        updateShelfIcons()
-        updateAodNotificationIcons()
-        applyNotificationIconsTint()
-        Trace.endSection()
-    }
-
-    private fun updateShelfIcons() {
-        if (shelfIcons == null) {
-            return
-        }
-        updateIconsForLayout(
-            { entry: NotificationEntry -> entry.icons.shelfIcon },
-            shelfIcons,
-            showAmbient = true,
-            showLowPriority = true,
-            hideDismissed = false,
-            hideRepliedMessages = false,
-            hideCurrentMedia = false,
-            hidePulsing = false
-        )
-    }
-
-    /**
-     * Updates the notification icons for a host layout. This will ensure that the notification host
-     * layout will have the same icons like the ones in here.
-     *
-     * @param function A function to look up an icon view based on an entry
-     * @param hostLayout which layout should be updated
-     * @param showAmbient should ambient notification icons be shown
-     * @param showLowPriority should icons from silent notifications be shown
-     * @param hideDismissed should dismissed icons be hidden
-     * @param hideRepliedMessages should messages that have been replied to be hidden
-     * @param hidePulsing should pulsing notifications be hidden
-     */
-    private fun updateIconsForLayout(
-        function: Function<NotificationEntry, StatusBarIconView?>,
-        hostLayout: NotificationIconContainer?,
-        showAmbient: Boolean,
-        showLowPriority: Boolean,
-        hideDismissed: Boolean,
-        hideRepliedMessages: Boolean,
-        hideCurrentMedia: Boolean,
-        hidePulsing: Boolean,
-    ) {
-        val toShow = ArrayList<StatusBarIconView>(notificationEntries.size)
-        // Filter out ambient notifications and notification children.
-        for (i in notificationEntries.indices) {
-            val entry = notificationEntries[i].representativeEntry
-            if (entry != null && entry.row != null) {
-                if (
-                    shouldShowNotificationIcon(
-                        entry,
-                        showAmbient,
-                        showLowPriority,
-                        hideDismissed,
-                        hideRepliedMessages,
-                        hideCurrentMedia,
-                        hidePulsing
-                    )
-                ) {
-                    val iconView = function.apply(entry)
-                    if (iconView != null) {
-                        toShow.add(iconView)
-                    }
-                }
-            }
-        }
-
-        // In case we are changing the suppression of a group, the replacement shouldn't flicker
-        // and it should just be replaced instead. We therefore look for notifications that were
-        // just replaced by the child or vice-versa to suppress this.
-        val replacingIcons = ArrayMap<String, ArrayList<StatusBarIcon>>()
-        val toRemove = ArrayList<View>()
-        for (i in 0 until hostLayout!!.childCount) {
-            val child = hostLayout.getChildAt(i) as? StatusBarIconView ?: continue
-            if (!toShow.contains(child)) {
-                var iconWasReplaced = false
-                val removedGroupKey = child.notification.groupKey
-                for (j in toShow.indices) {
-                    val candidate = toShow[j]
-                    if (
-                        candidate.sourceIcon.sameAs(child.sourceIcon) &&
-                            candidate.notification.groupKey == removedGroupKey
-                    ) {
-                        if (!iconWasReplaced) {
-                            iconWasReplaced = true
-                        } else {
-                            iconWasReplaced = false
-                            break
-                        }
-                    }
-                }
-                if (iconWasReplaced) {
-                    var statusBarIcons = replacingIcons[removedGroupKey]
-                    if (statusBarIcons == null) {
-                        statusBarIcons = ArrayList()
-                        replacingIcons[removedGroupKey] = statusBarIcons
-                    }
-                    statusBarIcons.add(child.statusBarIcon)
-                }
-                toRemove.add(child)
-            }
-        }
-        // removing all duplicates
-        val duplicates = ArrayList<String?>()
-        for (key in replacingIcons.keys) {
-            val statusBarIcons = replacingIcons[key]!!
-            if (statusBarIcons.size != 1) {
-                duplicates.add(key)
-            }
-        }
-        replacingIcons.removeAll(duplicates)
-        hostLayout.setReplacingIcons(replacingIcons)
-        val toRemoveCount = toRemove.size
-        for (i in 0 until toRemoveCount) {
-            hostLayout.removeView(toRemove[i])
-        }
-        val params = generateIconLayoutParams()
-        for (i in toShow.indices) {
-            val v = toShow[i]
-            // The view might still be transiently added if it was just removed and added again
-            hostLayout.removeTransientView(v)
-            if (v.parent == null) {
-                if (hideDismissed) {
-                    v.setOnDismissListener(updateStatusBarIcons)
-                }
-                hostLayout.addView(v, i, params)
-            }
-        }
-        hostLayout.setChangingViewPositions(true)
-        // Re-sort notification icons
-        val childCount = hostLayout.childCount
-        for (i in 0 until childCount) {
-            val actual = hostLayout.getChildAt(i)
-            val expected = toShow[i]
-            if (actual === expected) {
-                continue
-            }
-            hostLayout.removeView(expected)
-            hostLayout.addView(expected, i)
-        }
-        hostLayout.setChangingViewPositions(false)
-        hostLayout.setReplacingIcons(null)
-    }
-
-    /** Applies [.mIconTint] to the notification icons. */
-    private fun applyNotificationIconsTint() {
-        for (i in 0 until notificationIcons!!.childCount) {
-            val iv = notificationIcons!!.getChildAt(i) as StatusBarIconView
-            if (iv.width != 0) {
-                updateTintForIcon(iv, iconTint)
-            } else {
-                iv.executeOnLayout { updateTintForIcon(iv, iconTint) }
-            }
-        }
-        updateAodIconColors()
-    }
-
-    private fun updateTintForIcon(v: StatusBarIconView, tint: Int) {
-        val isPreL = java.lang.Boolean.TRUE == v.getTag(R.id.icon_is_pre_L)
-        var color = StatusBarIconView.NO_COLOR
-        val colorize = !isPreL || NotificationUtils.isGrayscale(v, contrastColorUtil)
-        if (colorize) {
-            color = DarkIconDispatcher.getTint(tintAreas, v, tint)
-        }
-        v.staticDrawableColor = color
-        v.setDecorColor(tint)
-    }
-
-    private fun reloadAodColor() {
-        aodIconTint =
-            Utils.getColorAttrDefaultColor(
-                context,
-                R.attr.wallpaperTextColor,
-                DEFAULT_AOD_ICON_COLOR
-            )
-    }
-
-    private fun updateAodIconColors() {
-        if (aodIcons != null) {
-            for (i in 0 until aodIcons!!.childCount) {
-                val iv = aodIcons!!.getChildAt(i) as StatusBarIconView
-                if (iv.width != 0) {
-                    updateTintForIcon(iv, aodIconTint)
-                } else {
-                    iv.executeOnLayout { updateTintForIcon(iv, aodIconTint) }
-                }
-            }
-        }
-    }
-
     companion object {
-        @ColorInt private val DEFAULT_AOD_ICON_COLOR = -0x1
-
         val unsupported: Nothing
             get() =
                 error(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
index 0d2f00a..c6d7e21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
@@ -15,27 +15,45 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewbinder
 
-import android.content.res.Resources
+import android.graphics.Rect
 import android.view.View
-import androidx.annotation.DimenRes
+import android.widget.FrameLayout
+import androidx.collection.ArrayMap
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.animation.Interpolators
+import com.android.internal.policy.SystemBarUtils
+import com.android.internal.util.ContrastColorUtil
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.CrossFadeHelper
+import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.notification.NotificationUtils
+import com.android.systemui.statusbar.notification.collection.NotifCollection
+import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder.IconViewStore
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconColors
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.NotificationIconContainer
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
+import com.android.systemui.statusbar.policy.onConfigChanged
+import com.android.systemui.util.children
+import com.android.systemui.util.kotlin.mapValuesNotNullTo
+import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.kotlin.stateFlow
-import kotlinx.coroutines.CoroutineScope
+import javax.inject.Inject
 import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
 /** Binds a [NotificationIconContainer] to its [view model][NotificationIconContainerViewModel]. */
@@ -43,52 +61,174 @@
     fun bind(
         view: NotificationIconContainer,
         viewModel: NotificationIconContainerViewModel,
+        configuration: ConfigurationState,
         configurationController: ConfigurationController,
         dozeParameters: DozeParameters,
         featureFlags: FeatureFlagsClassic,
         screenOffAnimationController: ScreenOffAnimationController,
+        viewStore: IconViewStore,
     ): DisposableHandle {
+        val contrastColorUtil = ContrastColorUtil.getInstance(view.context)
         return view.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
                 launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) }
                 launch {
                     viewModel.isDozing.collect { (isDozing, animate) ->
                         val animateIfNotBlanking = animate && !dozeParameters.displayNeedsBlanking
-                        view.setDozing(isDozing, animateIfNotBlanking, /* delay= */ 0) {
-                            viewModel.completeDozeAnimation()
-                        }
+                        view.setDozing(
+                            /* dozing = */ isDozing,
+                            /* fade = */ animateIfNotBlanking,
+                            /* delay = */ 0,
+                            /* endRunnable = */ viewModel::completeDozeAnimation,
+                        )
                     }
                 }
-                // TODO(278765923): this should live where AOD is bound, not inside of the NIC
+                // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC
                 //  view-binder
                 launch {
-                    val iconAppearTranslation =
-                        view.resources.getConfigAwareDimensionPixelSize(
-                            this,
-                            configurationController,
-                            R.dimen.shelf_appear_translation,
-                        )
                     bindVisibility(
                         viewModel,
                         view,
+                        configuration,
                         featureFlags,
                         screenOffAnimationController,
-                        iconAppearTranslation,
-                    ) {
-                        viewModel.completeVisibilityAnimation()
-                    }
+                        onAnimationEnd = viewModel::completeVisibilityAnimation,
+                    )
+                }
+                launch {
+                    viewModel.iconColors
+                        .mapNotNull { lookup -> lookup.iconColors(view.viewBounds) }
+                        .collect { iconLookup -> applyTint(view, iconLookup, contrastColorUtil) }
+                }
+                launch {
+                    bindIconViewData(
+                        viewModel,
+                        view,
+                        configuration,
+                        configurationController,
+                        viewStore,
+                    )
                 }
             }
         }
     }
+
+    private suspend fun bindIconViewData(
+        viewModel: NotificationIconContainerViewModel,
+        view: NotificationIconContainer,
+        configuration: ConfigurationState,
+        configurationController: ConfigurationController,
+        viewStore: IconViewStore,
+    ): Unit = coroutineScope {
+        val iconSizeFlow: Flow<Int> =
+            configuration.getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_icon_size_sp,
+            )
+        val iconHorizontalPaddingFlow: Flow<Int> =
+            configuration.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin)
+        val statusBarHeightFlow: StateFlow<Int> =
+            stateFlow(changedSignals = configurationController.onConfigChanged) {
+                SystemBarUtils.getStatusBarHeight(view.context)
+            }
+        val layoutParams: Flow<FrameLayout.LayoutParams> =
+            combine(iconSizeFlow, iconHorizontalPaddingFlow, statusBarHeightFlow) {
+                iconSize,
+                iconHPadding,
+                statusBarHeight,
+                ->
+                FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight)
+            }
+
+        launch {
+            layoutParams.collect { params: FrameLayout.LayoutParams ->
+                for (child in view.children) {
+                    child.layoutParams = params
+                }
+            }
+        }
+
+        var prevIcons = IconsViewData()
+        viewModel.iconsViewData.sample(layoutParams, ::Pair).collect {
+            (iconsData: IconsViewData, layoutParams: FrameLayout.LayoutParams),
+            ->
+            val iconsDiff = IconsViewData.computeDifference(iconsData, prevIcons)
+            prevIcons = iconsData
+
+            val replacingIcons =
+                iconsDiff.groupReplacements.mapValuesNotNullTo(ArrayMap()) { (_, v) ->
+                    viewStore.iconView(v.notifKey)?.statusBarIcon
+                }
+            view.setReplacingIcons(replacingIcons)
+
+            val childrenByNotifKey: Map<String, StatusBarIconView> =
+                view.children.filterIsInstance<StatusBarIconView>().associateByTo(ArrayMap()) {
+                    it.notification.key
+                }
+
+            iconsDiff.removed
+                .mapNotNull { key -> childrenByNotifKey[key] }
+                .forEach { child -> view.removeView(child) }
+
+            val toAdd = iconsDiff.added.mapNotNull { viewStore.iconView(it.notifKey) }
+            for ((i, sbiv) in toAdd.withIndex()) {
+                // The view might still be transiently added if it was just removed
+                // and added again
+                view.removeTransientView(sbiv)
+                view.addView(sbiv, i, layoutParams)
+            }
+
+            view.setChangingViewPositions(true)
+            // Re-sort notification icons
+            val childCount = view.childCount
+            for (i in 0 until childCount) {
+                val actual = view.getChildAt(i)
+                val expected = viewStore.iconView(iconsData.visibleKeys[i].notifKey)!!
+                if (actual === expected) {
+                    continue
+                }
+                view.removeView(expected)
+                view.addView(expected, i)
+            }
+            view.setChangingViewPositions(false)
+
+            view.setReplacingIcons(null)
+        }
+    }
+
+    // TODO(b/305739416): Once StatusBarIconView has its own Recommended Architecture stack, this
+    //  can be moved there and cleaned up.
+    private fun applyTint(
+        view: NotificationIconContainer,
+        iconColors: IconColors,
+        contrastColorUtil: ContrastColorUtil,
+    ) {
+        view.children
+            .filterIsInstance<StatusBarIconView>()
+            .filter { it.width != 0 }
+            .forEach { iv -> updateTintForIcon(iv, iconColors, contrastColorUtil) }
+    }
+
+    private fun updateTintForIcon(
+        v: StatusBarIconView,
+        iconColors: IconColors,
+        contrastColorUtil: ContrastColorUtil,
+    ) {
+        val isPreL = java.lang.Boolean.TRUE == v.getTag(R.id.icon_is_pre_L)
+        val isColorized = !isPreL || NotificationUtils.isGrayscale(v, contrastColorUtil)
+        v.staticDrawableColor = iconColors.staticDrawableColor(v.viewBounds, isColorized)
+        v.setDecorColor(iconColors.tint)
+    }
+
     private suspend fun bindVisibility(
         viewModel: NotificationIconContainerViewModel,
         view: NotificationIconContainer,
+        configuration: ConfigurationState,
         featureFlags: FeatureFlagsClassic,
         screenOffAnimationController: ScreenOffAnimationController,
-        iconAppearTranslation: StateFlow<Int>,
         onAnimationEnd: () -> Unit,
-    ) {
+    ): Unit = coroutineScope {
+        val iconAppearTranslation =
+            configuration.getDimensionPixelSize(R.dimen.shelf_appear_translation).stateIn(this)
         val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)
         viewModel.isVisible.collect { (isVisible, animate) ->
             view.animate().cancel()
@@ -173,14 +313,51 @@
     }
 
     private const val AOD_ICONS_APPEAR_DURATION: Long = 200
+
+    private val View.viewBounds: Rect
+        get() {
+            val tmpArray = intArrayOf(0, 0)
+            getLocationOnScreen(tmpArray)
+            return Rect(
+                /* left = */ tmpArray[0],
+                /* top = */ tmpArray[1],
+                /* right = */ left + width,
+                /* bottom = */ top + height,
+            )
+        }
+
+    /** External storage for [StatusBarIconView] instances. */
+    fun interface IconViewStore {
+        fun iconView(key: String): StatusBarIconView?
+    }
 }
 
-fun Resources.getConfigAwareDimensionPixelSize(
-    scope: CoroutineScope,
-    configurationController: ConfigurationController,
-    @DimenRes id: Int,
-): StateFlow<Int> =
-    scope.stateFlow(
-        changedSignals = configurationController.onDensityOrFontScaleChanged,
-        getValue = { getDimensionPixelSize(id) }
-    )
+/** [IconViewStore] for the [com.android.systemui.statusbar.NotificationShelf] */
+class ShelfNotificationIconViewStore
+@Inject
+constructor(
+    private val notifCollection: NotifCollection,
+) : IconViewStore {
+    override fun iconView(key: String): StatusBarIconView? =
+        notifCollection.getEntry(key)?.icons?.shelfIcon
+}
+
+/** [IconViewStore] for the always-on display. */
+class AlwaysOnDisplayNotificationIconViewStore
+@Inject
+constructor(
+    private val notifCollection: NotifCollection,
+) : IconViewStore {
+    override fun iconView(key: String): StatusBarIconView? =
+        notifCollection.getEntry(key)?.icons?.aodIcon
+}
+
+/** [IconViewStore] for the status bar. */
+class StatusBarNotificationIconViewStore
+@Inject
+constructor(
+    private val notifCollection: NotifCollection,
+) : IconViewStore {
+    override fun iconView(key: String): StatusBarIconView? =
+        notifCollection.getEntry(key)?.icons?.statusBarIcon
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
index 3289a3c..885f449e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
@@ -15,6 +15,10 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
+import android.graphics.Color
+import android.graphics.Rect
+import androidx.annotation.ColorInt
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.flags.FeatureFlagsClassic
@@ -23,8 +27,13 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
+import com.android.systemui.statusbar.notification.icon.domain.interactor.AlwaysOnDisplayNotificationIconsInteractor
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.ColorLookup
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconColors
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.util.kotlin.pairwise
@@ -44,9 +53,11 @@
 class NotificationIconContainerAlwaysOnDisplayViewModel
 @Inject
 constructor(
+    configuration: ConfigurationState,
     private val deviceEntryInteractor: DeviceEntryInteractor,
     private val dozeParameters: DozeParameters,
     private val featureFlags: FeatureFlagsClassic,
+    iconsInteractor: AlwaysOnDisplayNotificationIconsInteractor,
     keyguardInteractor: KeyguardInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor,
@@ -57,6 +68,11 @@
     private val onDozeAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
     private val onVisAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
 
+    override val iconColors: Flow<ColorLookup> =
+        configuration.getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR).map { tint ->
+            ColorLookup { IconColorsImpl(tint) }
+        }
+
     override val animationsEnabled: Flow<Boolean> =
         combine(
             shadeInteractor.isShadeTouchable,
@@ -121,14 +137,19 @@
         onVisAnimationComplete.tryEmit(Unit)
     }
 
+    override val iconsViewData: Flow<IconsViewData> =
+        iconsInteractor.aodNotifs.map { entries ->
+            IconsViewData(
+                visibleKeys = entries.mapNotNull { it.toIconInfo(it.aodIcon) },
+            )
+        }
+
     /** Is there an expanded pulse, are we animating in response? */
     private fun isPulseExpandingAnimated(): Flow<AnimatedValue<Boolean>> {
         return notificationsKeyguardInteractor.isPulseExpanding
             .pairwise(initialValue = null)
             // If pulsing changes, start animating, unless it's the first emission
-            .map { (prev, expanding) ->
-                AnimatableEvent(expanding!!, startAnimating = prev != null)
-            }
+            .map { (prev, expanding) -> AnimatableEvent(expanding, startAnimating = prev != null) }
             .toAnimatedValueFlow(completionEvents = onVisAnimationComplete)
     }
 
@@ -151,10 +172,18 @@
                         // We only want the appear animations to happen when the notifications
                         // get fully hidden, since otherwise the un-hide animation overlaps.
                         featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> true
-                        else -> fullyHidden!!
+                        else -> fullyHidden
                     }
-                AnimatableEvent(fullyHidden!!, animate)
+                AnimatableEvent(fullyHidden, animate)
             }
             .toAnimatedValueFlow(completionEvents = onVisAnimationComplete)
     }
+
+    private class IconColorsImpl(override val tint: Int) : IconColors {
+        override fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int = tint
+    }
+
+    companion object {
+        @ColorInt private val DEFAULT_AOD_ICON_COLOR = Color.WHITE
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
index c44a2b6..38eae24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
@@ -15,18 +15,33 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
+import com.android.systemui.statusbar.notification.icon.domain.interactor.NotificationIconsInteractor
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.ColorLookup
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData
 import com.android.systemui.util.ui.AnimatedValue
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
 
 /** View-model for the overflow row of notification icons displayed in the notification shade. */
-class NotificationIconContainerShelfViewModel @Inject constructor() :
-    NotificationIconContainerViewModel {
+class NotificationIconContainerShelfViewModel
+@Inject
+constructor(
+    interactor: NotificationIconsInteractor,
+) : NotificationIconContainerViewModel {
     override val animationsEnabled: Flow<Boolean> = flowOf(true)
     override val isDozing: Flow<AnimatedValue<Boolean>> = emptyFlow()
     override val isVisible: Flow<AnimatedValue<Boolean>> = emptyFlow()
     override fun completeDozeAnimation() {}
     override fun completeVisibilityAnimation() {}
+    override val iconColors: Flow<ColorLookup> = emptyFlow()
+
+    override val iconsViewData: Flow<IconsViewData> =
+        interactor.filteredNotifSet().map { entries ->
+            IconsViewData(
+                visibleKeys = entries.mapNotNull { it.toIconInfo(it.shelfIcon) },
+            )
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
index 035687a..cdbabb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
@@ -15,19 +15,31 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
+import android.graphics.Rect
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.icon.domain.interactor.StatusBarNotificationIconsInteractor
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.ColorLookup
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconColors
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconsViewData
+import com.android.systemui.statusbar.phone.domain.interactor.DarkIconInteractor
 import com.android.systemui.util.ui.AnimatedValue
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.map
 
 /** View-model for the row of notification icons displayed in the status bar, */
 class NotificationIconContainerStatusBarViewModel
 @Inject
 constructor(
+    darkIconInteractor: DarkIconInteractor,
+    iconsInteractor: StatusBarNotificationIconsInteractor,
     keyguardInteractor: KeyguardInteractor,
+    notificationsInteractor: ActiveNotificationsInteractor,
     shadeInteractor: ShadeInteractor,
 ) : NotificationIconContainerViewModel {
     override val animationsEnabled: Flow<Boolean> =
@@ -38,8 +50,44 @@
             panelTouchesEnabled && !isKeyguardShowing
         }
 
+    override val iconColors: Flow<ColorLookup> =
+        combine(
+            darkIconInteractor.tintAreas,
+            darkIconInteractor.tintColor,
+            // Included so that tints are re-applied after entries are changed.
+            notificationsInteractor.notifications,
+        ) { areas, tint, _ ->
+            ColorLookup { viewBounds: Rect ->
+                if (DarkIconDispatcher.isInAreas(areas, viewBounds)) {
+                    IconColorsImpl(tint, areas)
+                } else {
+                    null
+                }
+            }
+        }
+
     override val isDozing: Flow<AnimatedValue<Boolean>> = emptyFlow()
     override val isVisible: Flow<AnimatedValue<Boolean>> = emptyFlow()
     override fun completeDozeAnimation() {}
     override fun completeVisibilityAnimation() {}
+
+    override val iconsViewData: Flow<IconsViewData> =
+        iconsInteractor.statusBarNotifs.map { entries ->
+            IconsViewData(
+                visibleKeys = entries.mapNotNull { it.toIconInfo(it.statusBarIcon) },
+            )
+        }
+
+    private class IconColorsImpl(
+        override val tint: Int,
+        private val areas: Collection<Rect>,
+    ) : IconColors {
+        override fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int {
+            return if (isColorized && DarkIconDispatcher.isInAreas(areas, viewBounds)) {
+                tint
+            } else {
+                DarkIconDispatcher.DEFAULT_ICON_TINT
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
index 65eb220..0e8dfea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
@@ -15,6 +15,12 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
+import android.graphics.Rect
+import android.graphics.drawable.Icon
+import androidx.collection.ArrayMap
+import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel.IconInfo
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.util.kotlin.mapValuesNotNullTo
 import com.android.systemui.util.ui.AnimatedValue
 import kotlinx.coroutines.flow.Flow
 
@@ -23,6 +29,7 @@
  * AOD.
  */
 interface NotificationIconContainerViewModel {
+
     /** Are changes to the icon container animated? */
     val animationsEnabled: Flow<Boolean>
 
@@ -32,15 +39,164 @@
     /** Is the icon container visible? */
     val isVisible: Flow<AnimatedValue<Boolean>>
 
+    /** The colors with which to display the notification icons. */
+    val iconColors: Flow<ColorLookup>
+
+    /** [IconsViewData] indicating which icons to display in the view. */
+    val iconsViewData: Flow<IconsViewData>
+
     /**
      * Signal completion of the [isDozing] animation; if [isDozing]'s [AnimatedValue.isAnimating]
-     * property was `true`, calling this method will update it to `false.
+     * property was `true`, calling this method will update it to `false`.
      */
     fun completeDozeAnimation()
 
     /**
      * Signal completion of the [isVisible] animation; if [isVisible]'s [AnimatedValue.isAnimating]
-     * property was `true`, calling this method will update it to `false.
+     * property was `true`, calling this method will update it to `false`.
      */
     fun completeVisibilityAnimation()
+
+    /**
+     * Lookup the colors to use for the notification icons based on the bounds of the icon
+     * container. A result of `null` indicates that no color changes should be applied.
+     */
+    fun interface ColorLookup {
+        fun iconColors(viewBounds: Rect): IconColors?
+    }
+
+    /** Colors to apply to notification icons. */
+    interface IconColors {
+
+        /** A tint to apply to the icons. */
+        val tint: Int
+
+        /**
+         * Returns the color to be applied to an icon, based on that icon's view bounds and whether
+         * or not the notification icon is colorized.
+         */
+        fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int
+    }
+
+    /** Encapsulates the collection of notification icons present on the device. */
+    data class IconsViewData(
+        /** Icons that are visible in the container. */
+        val visibleKeys: List<IconInfo> = emptyList(),
+        /** Keys of icons that are "behind" the overflow dot. */
+        val collapsedKeys: Set<String> = emptySet(),
+        /** Whether the overflow dot should be shown regardless if [collapsedKeys] is empty. */
+        val forceShowDot: Boolean = false,
+    ) {
+        /** The difference between two [IconsViewData]s. */
+        data class Diff(
+            /** Icons added in the newer dataset. */
+            val added: List<IconInfo> = emptyList(),
+            /** Icons removed from the older dataset. */
+            val removed: List<String> = emptyList(),
+            /**
+             * Groups whose icon was replaced with a single new notification icon. The key of the
+             * [Map] is the notification group key, and the value is the new icon.
+             *
+             * Specifically, this models a difference where the older dataset had notification
+             * groups with a single icon in the set, and the newer dataset has a single, different
+             * icon for the same group. A view binder can use this information for special
+             * animations for this specific change.
+             */
+            val groupReplacements: Map<String, IconInfo> = emptyMap(),
+        )
+
+        companion object {
+            /**
+             * Returns an [IconsViewData.Diff] calculated from a [new] and [previous][prev]
+             * [IconsViewData] state.
+             */
+            fun computeDifference(new: IconsViewData, prev: IconsViewData): Diff {
+                val added: List<IconInfo> =
+                    new.visibleKeys.filter {
+                        it.notifKey !in prev.visibleKeys.asSequence().map { it.notifKey }
+                    }
+                val removed: List<IconInfo> =
+                    prev.visibleKeys.filter {
+                        it.notifKey !in new.visibleKeys.asSequence().map { it.notifKey }
+                    }
+                val groupsToShow: Set<IconGroupInfo> =
+                    new.visibleKeys.asSequence().map { it.groupInfo }.toSet()
+                val replacements: ArrayMap<String, IconInfo> =
+                    removed
+                        .asSequence()
+                        .filter { keyToRemove -> keyToRemove.groupInfo in groupsToShow }
+                        .groupBy { it.groupInfo.groupKey }
+                        .mapValuesNotNullTo(ArrayMap()) { (_, vs) ->
+                            vs.takeIf { it.size == 1 }?.get(0)
+                        }
+                return Diff(added, removed.map { it.notifKey }, replacements)
+            }
+        }
+    }
+
+    /** An Icon, and keys for unique identification. */
+    data class IconInfo(
+        val sourceIcon: Icon,
+        val notifKey: String,
+        val groupKey: String,
+    )
+}
+
+/**
+ * Construct an [IconInfo] out of an [ActiveNotificationModel], or return `null` if one cannot be
+ * created due to missing information.
+ */
+fun ActiveNotificationModel.toIconInfo(sourceIcon: Icon?): IconInfo? {
+    return sourceIcon?.let {
+        groupKey?.let { groupKey ->
+            IconInfo(
+                sourceIcon = sourceIcon,
+                notifKey = key,
+                groupKey = groupKey,
+            )
+        }
+    }
+}
+
+private val IconInfo.groupInfo: IconGroupInfo
+    get() = IconGroupInfo(sourceIcon, groupKey)
+
+private data class IconGroupInfo(
+    val sourceIcon: Icon,
+    val groupKey: String,
+) {
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as IconGroupInfo
+
+        if (groupKey != other.groupKey) return false
+        return sourceIcon.sameAs(other.sourceIcon)
+    }
+
+    override fun hashCode(): Int {
+        var result = groupKey.hashCode()
+        result = 31 * result + sourceIcon.type.hashCode()
+        when (sourceIcon.type) {
+            Icon.TYPE_BITMAP,
+            Icon.TYPE_ADAPTIVE_BITMAP -> {
+                result = 31 * result + sourceIcon.bitmap.hashCode()
+            }
+            Icon.TYPE_DATA -> {
+                result = 31 * result + sourceIcon.dataLength.hashCode()
+                result = 31 * result + sourceIcon.dataOffset.hashCode()
+            }
+            Icon.TYPE_RESOURCE -> {
+                result = 31 * result + sourceIcon.resId.hashCode()
+                result = 31 * result + sourceIcon.resPackage.hashCode()
+            }
+            Icon.TYPE_URI,
+            Icon.TYPE_URI_ADAPTIVE_BITMAP -> {
+                result = 31 * result + sourceIcon.uriString.hashCode()
+            }
+        }
+        return result
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
new file mode 100644
index 0000000..78370ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.shared
+
+import android.graphics.drawable.Icon
+
+/** Model for entries in the notification stack. */
+data class ActiveNotificationModel(
+    /** Notification key associated with this entry. */
+    val key: String,
+    /** Notification group key associated with this entry. */
+    val groupKey: String?,
+    /** Is this entry in the ambient / minimized section (lowest priority)? */
+    val isAmbient: Boolean,
+    /**
+     * Is this entry dismissed? This is `true` when the user has dismissed the notification in the
+     * UI, but `NotificationManager` has not yet signalled to us that it has received the dismissal.
+     */
+    val isRowDismissed: Boolean,
+    /** Is this entry in the silent section? */
+    val isSilent: Boolean,
+    /**
+     * Does this entry represent a conversation, the last message of which was from a remote input
+     * reply?
+     */
+    val isLastMessageFromReply: Boolean,
+    /** Is this entry suppressed from appearing in the status bar as an icon? */
+    val isSuppressedFromStatusBar: Boolean,
+    /** Is this entry actively pulsing on AOD or bypassed-keyguard? */
+    val isPulsing: Boolean,
+    /** Icon to display on AOD. */
+    val aodIcon: Icon?,
+    /** Icon to display in the notification shelf. */
+    val shelfIcon: Icon?,
+    /** Icon to display in the status bar. */
+    val statusBarIcon: Icon?,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index e4d96c3..6bb9573 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -67,18 +67,6 @@
     void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer);
 
     /**
-     * Generate an animation for an added child view.
-     *  @param child The view to be added.
-     * @param fromMoreCard Whether this add is coming from the "more" card on lockscreen.
-     */
-    void generateAddAnimation(ExpandableView child, boolean fromMoreCard);
-
-    /**
-     * Generate a child order changed event.
-     */
-    void generateChildOrderChangedEvent();
-
-    /**
      * Returns the number of children in the NotificationListContainer.
      *
      * @return the number of children in the NotificationListContainer
@@ -187,21 +175,6 @@
     default void bindRow(ExpandableNotificationRow row) {}
 
     /**
-     * Does this list contain a given view. True by default is fine, since we only ask this if the
-     * view has a parent.
-     */
-    default boolean containsView(View v) {
-        return true;
-    }
-
-    /**
-     * Tells the container that an animation is about to expand it.
-     */
-    default void setWillExpand(boolean willExpand) {}
-
-    void setNotificationActivityStarter(NotificationActivityStarter notificationActivityStarter);
-
-    /**
      * @return the start location where we start clipping notifications.
      */
     default int getTopClippingStartLocation() {
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 dba93d9..1e9cfa8 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
@@ -107,6 +107,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
 import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -324,7 +325,6 @@
     private NotificationsController mNotificationsController;
     private ActivityStarter mActivityStarter;
     private final int[] mTempInt2 = new int[2];
-    private boolean mGenerateChildOrderChangedEvent;
     private final HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
     private final HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
     private final HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
@@ -695,7 +695,9 @@
         super.onFinishInflate();
 
         inflateEmptyShadeView();
-        inflateFooterView();
+        if (!FooterViewRefactor.isEnabled()) {
+            inflateFooterView();
+        }
     }
 
     /**
@@ -730,9 +732,11 @@
     }
 
     void reinflateViews() {
-        inflateFooterView();
+        if (!FooterViewRefactor.isEnabled()) {
+            inflateFooterView();
+            updateFooter();
+        }
         inflateEmptyShadeView();
-        updateFooter();
         mSectionsManager.reinflateViews();
     }
 
@@ -747,7 +751,7 @@
 
     @VisibleForTesting
     public void updateFooter() {
-        if (mFooterView == null) {
+        if (mFooterView == null || mController == null) {
             return;
         }
         // TODO: move this logic to controller, which will invoke updateFooterView directly
@@ -3144,10 +3148,6 @@
         requestChildrenUpdate();
     }
 
-    public boolean containsView(View v) {
-        return v.getParent() == this;
-    }
-
     public void applyLaunchAnimationParams(LaunchAnimationParameters params) {
         // Modify the clipping for launching notifications
         mLaunchAnimationParams = params;
@@ -3410,11 +3410,6 @@
             mAnimationEvents.add(animEvent);
         }
         mChildrenChangingPositions.clear();
-        if (mGenerateChildOrderChangedEvent) {
-            mAnimationEvents.add(new AnimationEvent(null,
-                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
-            mGenerateChildOrderChangedEvent = false;
-        }
     }
 
     private void generateChildAdditionEvents() {
@@ -4556,7 +4551,8 @@
         return mFooterView != null && mFooterView.isHistoryShown();
     }
 
-    void setFooterView(@NonNull FooterView footerView) {
+    /** Bind the {@link FooterView} to the NSSL. */
+    public void setFooterView(@NonNull FooterView footerView) {
         int index = -1;
         if (mFooterView != null) {
             index = indexOfChild(mFooterView);
@@ -4567,6 +4563,16 @@
         if (mManageButtonClickListener != null) {
             mFooterView.setManageButtonClickListener(mManageButtonClickListener);
         }
+        mFooterView.setClearAllButtonClickListener(v -> {
+            if (mFooterClearAllListener != null) {
+                mFooterClearAllListener.onClearAll();
+            }
+            clearNotifications(ROWS_ALL, true /* closeShade */);
+            footerView.setSecondaryVisible(false /* visible */, true /* animate */);
+        });
+        if (FooterViewRefactor.isEnabled()) {
+            updateFooter();
+        }
     }
 
     public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
@@ -4629,7 +4635,9 @@
         mFooterView.setVisible(visible, animate);
         mFooterView.setSecondaryVisible(showDismissView, animate);
         mFooterView.showHistory(showHistory);
-        mFooterView.setFooterLabelVisible(mHasFilteredOutSeenNotifications);
+        if (!FooterViewRefactor.isEnabled()) {
+            mFooterView.setFooterLabelVisible(mHasFilteredOutSeenNotifications);
+        }
     }
 
     @VisibleForTesting
@@ -4764,14 +4772,6 @@
         info.setClassName(ScrollView.class.getName());
     }
 
-    public void generateChildOrderChangedEvent() {
-        if (mIsExpanded && mAnimationsEnabled) {
-            mGenerateChildOrderChangedEvent = true;
-            mNeedsAnimation = true;
-            requestChildrenUpdate();
-        }
-    }
-
     public int getContainerChildCount() {
         return getChildCount();
     }
@@ -5388,15 +5388,9 @@
 
     @VisibleForTesting
     protected void inflateFooterView() {
+        FooterViewRefactor.assertInLegacyMode();
         FooterView footerView = (FooterView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_notification_footer, this, false);
-        footerView.setClearAllButtonClickListener(v -> {
-            if (mFooterClearAllListener != null) {
-                mFooterClearAllListener.onClearAll();
-            }
-            clearNotifications(ROWS_ALL, true /* closeShade */);
-            footerView.setSecondaryVisible(false /* visible */, true /* animate */);
-        });
         setFooterView(footerView);
     }
 
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 6a70815..79448b4 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
@@ -62,7 +62,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.FeatureFlagsClassic;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.flags.RefactorFlag;
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
@@ -106,6 +106,7 @@
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
+import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -114,7 +115,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationGuts;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.row.NotificationSnooze;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor;
 import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
@@ -194,7 +194,7 @@
 
     private final GroupExpansionManager mGroupExpansionManager;
     private final NotifPipelineFlags mNotifPipelineFlags;
-    private final NotificationListInteractor mNotificationListInteractor;
+    private final SeenNotificationsInteractor mSeenNotificationsInteractor;
     private final KeyguardTransitionRepository mKeyguardTransitionRepo;
 
     private NotificationStackScrollLayout mView;
@@ -206,7 +206,7 @@
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private boolean mIsInTransitionToAod = false;
 
-    private final FeatureFlags mFeatureFlags;
+    private final FeatureFlagsClassic mFeatureFlags;
     private final RefactorFlag mShelfRefactor;
     private final NotificationTargetsHelper mNotificationTargetsHelper;
     private final SecureSettings mSecureSettings;
@@ -662,14 +662,14 @@
             UiEventLogger uiEventLogger,
             NotificationRemoteInputManager remoteInputManager,
             VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
-            NotificationListInteractor notificationListInteractor,
+            SeenNotificationsInteractor seenNotificationsInteractor,
             ShadeController shadeController,
             InteractionJankMonitor jankMonitor,
             StackStateLogger stackLogger,
             NotificationStackScrollLogger logger,
             NotificationStackSizeCalculator notificationStackSizeCalculator,
             NotificationIconAreaController notifIconAreaController,
-            FeatureFlags featureFlags,
+            FeatureFlagsClassic featureFlags,
             NotificationTargetsHelper notificationTargetsHelper,
             SecureSettings secureSettings,
             NotificationDismissibilityProvider dismissibilityProvider,
@@ -715,7 +715,7 @@
         mUiEventLogger = uiEventLogger;
         mRemoteInputManager = remoteInputManager;
         mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
-        mNotificationListInteractor = notificationListInteractor;
+        mSeenNotificationsInteractor = seenNotificationsInteractor;
         mShadeController = shadeController;
         mNotifIconAreaController = notifIconAreaController;
         mFeatureFlags = featureFlags;
@@ -832,7 +832,8 @@
 
         mViewModel.ifPresent(
                 vm -> NotificationListViewBinder
-                        .bind(mView, vm, mFalsingManager, mFeatureFlags, mNotifIconAreaController));
+                        .bind(mView, vm, mFalsingManager, mFeatureFlags, mNotifIconAreaController,
+                                mConfigurationController));
 
         collectFlow(mView, mKeyguardTransitionRepo.getTransitions(),
                 this::onKeyguardTransitionChanged);
@@ -1725,28 +1726,11 @@
         }
 
         @Override
-        public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
-            mView.generateAddAnimation(child, fromMoreCard);
-        }
-
-        @Override
-        public void generateChildOrderChangedEvent() {
-            mView.generateChildOrderChangedEvent();
-        }
-
-        @Override
         public int getContainerChildCount() {
             return mView.getContainerChildCount();
         }
 
         @Override
-        public void setNotificationActivityStarter(
-                NotificationActivityStarter notificationActivityStarter) {
-            NotificationStackScrollLayoutController.this
-                    .setNotificationActivityStarter(notificationActivityStarter);
-        }
-
-        @Override
         public int getTopClippingStartLocation() {
             return mView.getTopClippingStartLocation();
         }
@@ -1841,16 +1825,6 @@
         }
 
         @Override
-        public boolean containsView(View v) {
-            return mView.containsView(v);
-        }
-
-        @Override
-        public void setWillExpand(boolean willExpand) {
-            mView.setWillExpand(willExpand);
-        }
-
-        @Override
         public void dumpPipeline(@NonNull PipelineDumper d) {
             d.dump("NotificationStackScrollLayoutController.this",
                     NotificationStackScrollLayoutController.this);
@@ -2006,7 +1980,7 @@
         public void setNotifStats(@NonNull NotifStats notifStats) {
             mNotifStats = notifStats;
             mView.setHasFilteredOutSeenNotifications(
-                    mNotificationListInteractor.getHasFilteredOutSeenNotifications().getValue());
+                    mSeenNotificationsInteractor.getHasFilteredOutSeenNotifications().getValue());
             updateFooter();
             updateShowEmptyShadeView();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt
deleted file mode 100644
index f6ed8c8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.stack.data.repository
-
-import com.android.systemui.dagger.SysUISingleton
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-/** Repository for information about the current notification list. */
-@SysUISingleton
-class NotificationListRepository @Inject constructor() {
-    private val _hasFilteredOutSeenNotifications = MutableStateFlow(false)
-    val hasFilteredOutSeenNotifications: StateFlow<Boolean> =
-        _hasFilteredOutSeenNotifications.asStateFlow()
-
-    fun setHasFilteredOutSeenNotifications(value: Boolean) {
-        _hasFilteredOutSeenNotifications.value = value
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index dee3973..a3792cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -17,14 +17,23 @@
 package com.android.systemui.statusbar.notification.stack.ui.viewbinder
 
 import android.view.LayoutInflater
-import com.android.systemui.res.R
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.NotificationShelf
+import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
+import com.android.systemui.statusbar.notification.footer.ui.viewbinder.FooterViewBinder
 import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinder
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
+import com.android.systemui.statusbar.policy.onThemeChanged
+import com.android.systemui.util.traceSection
+import com.android.systemui.util.view.reinflateAndBindLatest
+import kotlinx.coroutines.flow.merge
 
 /** Binds a [NotificationStackScrollLayout] to its [view model][NotificationListViewModel]. */
 object NotificationListViewBinder {
@@ -33,8 +42,9 @@
         view: NotificationStackScrollLayout,
         viewModel: NotificationListViewModel,
         falsingManager: FalsingManager,
-        featureFlags: FeatureFlags,
+        featureFlags: FeatureFlagsClassic,
         iconAreaController: NotificationIconAreaController,
+        configurationController: ConfigurationController,
     ) {
         val shelf =
             LayoutInflater.from(view.context)
@@ -47,5 +57,26 @@
             iconAreaController
         )
         view.setShelf(shelf)
+
+        viewModel.footer.ifPresent { footerViewModel ->
+            // The footer needs to be re-inflated every time the theme or the font size changes.
+            view.repeatWhenAttached {
+                LayoutInflater.from(view.context).reinflateAndBindLatest(
+                    R.layout.status_bar_notification_footer,
+                    view,
+                    attachToRoot = false,
+                    // TODO(b/305930747): This may lead to duplicate invocations if both flows emit,
+                    // find a solution to only emit one event.
+                    merge(
+                        configurationController.onThemeChanged,
+                        configurationController.onDensityOrFontScaleChanged,
+                    ),
+                ) { view ->
+                    traceSection("bind FooterView") {
+                        FooterViewBinder.bind(view as FooterView, footerViewModel)
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index 11f68e0..261371d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -17,8 +17,9 @@
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModel
 import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
 import dagger.Module
 import dagger.Provides
@@ -28,6 +29,7 @@
 /** ViewModel for the list of notifications. */
 class NotificationListViewModel(
     val shelf: NotificationShelfViewModel,
+    val footer: Optional<FooterViewModel>,
 )
 
 @Module
@@ -36,12 +38,33 @@
     @Provides
     @SysUISingleton
     fun maybeProvideViewModel(
-        featureFlags: FeatureFlags,
+        featureFlags: FeatureFlagsClassic,
         shelfViewModel: Provider<NotificationShelfViewModel>,
-    ): Optional<NotificationListViewModel> =
-        if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
-            Optional.of(NotificationListViewModel(shelfViewModel.get()))
+        footerViewModel: Provider<FooterViewModel>,
+    ): Optional<NotificationListViewModel> {
+        return if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
+            if (com.android.systemui.Flags.notificationsFooterViewRefactor()) {
+                Optional.of(
+                    NotificationListViewModel(
+                        shelfViewModel.get(),
+                        Optional.of(footerViewModel.get())
+                    )
+                )
+            } else {
+                Optional.of(NotificationListViewModel(shelfViewModel.get(), Optional.empty()))
+            }
         } else {
+            if (com.android.systemui.Flags.notificationsFooterViewRefactor()) {
+                throw IllegalStateException(
+                    "The com.android.systemui.notifications_footer_view_refactor flag requires " +
+                        "the notification_shelf_refactor flag to be enabled. First disable the " +
+                        "footer flag using `adb shell device_config put systemui " +
+                        "com.android.systemui.notifications_footer_view_refactor false`, then " +
+                        "enable the notification_shelf_refactor flag in Flag Flipper. " +
+                        "Afterwards, you can try re-enabling the footer refactor flag via adb."
+                )
+            }
             Optional.empty()
         }
+    }
 }
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 7cd32f9..f41b7df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -3106,7 +3106,9 @@
             }
             // TODO: Bring these out of CentralSurfaces.
             mUserInfoControllerImpl.onDensityOrFontScaleChanged();
-            mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
+            if (!mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+                mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
+            }
         }
 
         @Override
@@ -3124,7 +3126,9 @@
             if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
                 ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
             }
-            mNotificationIconAreaController.onThemeChanged();
+            if (!mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+                mNotificationIconAreaController.onThemeChanged();
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index d3d11ea..66341ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -37,6 +37,8 @@
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.flags.FeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -82,6 +84,7 @@
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final HeadsUpManager mHeadsUpManager;
+    private final FeatureFlagsClassic mFeatureFlags;
     private final BatteryController mBatteryController;
     private final ScrimController mScrimController;
     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@@ -107,6 +110,7 @@
             WakefulnessLifecycle wakefulnessLifecycle,
             SysuiStatusBarStateController statusBarStateController,
             DeviceProvisionedController deviceProvisionedController,
+            FeatureFlagsClassic featureFlags,
             HeadsUpManager headsUpManager, BatteryController batteryController,
             ScrimController scrimController,
             Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
@@ -130,6 +134,7 @@
         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
         mAssistManagerLazy = assistManagerLazy;
         mDozeScrimController = dozeScrimController;
+        mFeatureFlags = featureFlags;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mPulseExpansionHandler = pulseExpansionHandler;
         mNotificationShadeWindowController = notificationShadeWindowController;
@@ -173,8 +178,13 @@
 
     void fireNotificationPulse(NotificationEntry entry) {
         Runnable pulseSuppressedListener = () -> {
-            entry.setPulseSuppressed(true);
-            mNotificationIconAreaController.updateAodNotificationIcons();
+            if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+                mHeadsUpManager.removeNotification(
+                        entry.getKey(), /* releaseImmediately= */ true, /* animate= */ false);
+            } else {
+                entry.setPulseSuppressed(true);
+                mNotificationIconAreaController.updateAodNotificationIcons();
+            }
         };
         Assert.isMainThread();
         for (Callback callback : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
index f9856b0..4284c96c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java
@@ -448,7 +448,7 @@
             }
         }
         replacingIcons.removeAll(duplicates);
-        hostLayout.setReplacingIcons(replacingIcons);
+        hostLayout.setReplacingIconsLegacy(replacingIcons);
 
         final int toRemoveCount = toRemove.size();
         for (int i = 0; i < toRemoveCount; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index b15c0fd..d70edbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -40,6 +40,8 @@
 import com.android.app.animation.Interpolators;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.settingslib.Utils;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.RefactorFlag;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.stack.AnimationFilter;
@@ -48,7 +50,9 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 /**
  * A container for notification icons. It handles overflowing icons properly and positions them
@@ -131,6 +135,9 @@
         }
     }.setDuration(CONTENT_FADE_DURATION);
 
+    private final RefactorFlag mIconContainerRefactorFlag =
+            RefactorFlag.forView(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR);
+
     /* Maximum number of icons on AOD when also showing overflow dot. */
     private int mMaxIconsOnAod;
 
@@ -156,7 +163,8 @@
     private int mIconSize;
     private boolean mDisallowNextAnimation;
     private boolean mAnimationsEnabled = true;
-    private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
+    private ArrayMap<String, StatusBarIcon> mReplacingIcons;
+    private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIconsLegacy;
     // Keep track of the last visible icon so collapsed container can report on its location
     private IconState mLastVisibleIconState;
     private IconState mFirstVisibleIconState;
@@ -339,23 +347,29 @@
     }
 
     private boolean isReplacingIcon(View child) {
-        if (mReplacingIcons == null) {
-            return false;
-        }
         if (!(child instanceof StatusBarIconView)) {
             return false;
         }
         StatusBarIconView iconView = (StatusBarIconView) child;
         Icon sourceIcon = iconView.getSourceIcon();
         String groupKey = iconView.getNotification().getGroupKey();
-        ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
-        if (statusBarIcons != null) {
-            StatusBarIcon replacedIcon = statusBarIcons.get(0);
-            if (sourceIcon.sameAs(replacedIcon.icon)) {
-                return true;
+        if (mIconContainerRefactorFlag.isEnabled()) {
+            if (mReplacingIcons == null) {
+                return false;
             }
+            StatusBarIcon replacedIcon = mReplacingIcons.get(groupKey);
+            return replacedIcon != null && sourceIcon.sameAs(replacedIcon.icon);
+        } else {
+            if (mReplacingIconsLegacy == null) {
+                return false;
+            }
+            ArrayList<StatusBarIcon> statusBarIcons = mReplacingIconsLegacy.get(groupKey);
+            if (statusBarIcons != null) {
+                StatusBarIcon replacedIcon = statusBarIcons.get(0);
+                return sourceIcon.sameAs(replacedIcon.icon);
+            }
+            return false;
         }
-        return false;
     }
 
     @Override
@@ -681,7 +695,13 @@
         mAnimationsEnabled = enabled;
     }
 
-    public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+    public void setReplacingIconsLegacy(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+        mIconContainerRefactorFlag.assertInLegacyMode();
+        mReplacingIconsLegacy = replacingIcons;
+    }
+
+    public void setReplacingIcons(ArrayMap<String, StatusBarIcon> replacingIcons) {
+        if (mIconContainerRefactorFlag.isUnexpectedlyInLegacyMode()) return;
         mReplacingIcons = replacingIcons;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index a5cd062..07e2571 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -52,7 +52,7 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
-import com.android.systemui.statusbar.notification.domain.interactor.NotificationsInteractor;
+import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -80,7 +80,7 @@
     private final HeadsUpManager mHeadsUpManager;
     private final AboveShelfObserver mAboveShelfObserver;
     private final DozeScrimController mDozeScrimController;
-    private final NotificationsInteractor mNotificationsInteractor;
+    private final NotificationAlertsInteractor mNotificationAlertsInteractor;
     private final NotificationStackScrollLayoutController mNsslController;
     private final LockscreenShadeTransitionController mShadeTransitionController;
     private final PowerInteractor mPowerInteractor;
@@ -107,7 +107,7 @@
             NotificationShadeWindowController notificationShadeWindowController,
             DynamicPrivacyController dynamicPrivacyController,
             KeyguardStateController keyguardStateController,
-            NotificationsInteractor notificationsInteractor,
+            NotificationAlertsInteractor notificationAlertsInteractor,
             LockscreenShadeTransitionController shadeTransitionController,
             PowerInteractor powerInteractor,
             CommandQueue commandQueue,
@@ -127,7 +127,7 @@
         mQsController = quickSettingsController;
         mHeadsUpManager = headsUp;
         mDynamicPrivacyController = dynamicPrivacyController;
-        mNotificationsInteractor = notificationsInteractor;
+        mNotificationAlertsInteractor = notificationAlertsInteractor;
         mNsslController = stackScrollerController;
         mShadeTransitionController = shadeTransitionController;
         mPowerInteractor = powerInteractor;
@@ -303,7 +303,7 @@
 
         @Override
         public boolean suppressInterruptions(NotificationEntry entry) {
-            return !mNotificationsInteractor.areNotificationAlertsEnabled();
+            return !mNotificationAlertsInteractor.areNotificationAlertsEnabled();
         }
     };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
index d7f3b07..71e25e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialog.kt
@@ -77,11 +77,15 @@
         configurationController?.removeCallback(onConfigChanged)
     }
 
+    /** Can be overridden by subclasses to receive config changed events. */
+    open fun onConfigurationChanged() {}
+
     private val onConfigChanged =
         object : ConfigurationListener {
             override fun onConfigChanged(newConfig: Configuration?) {
                 super.onConfigChanged(newConfig)
                 setupEdgeToEdge()
+                onConfigurationChanged()
             }
         }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/StatusBarPhoneDataLayerModule.kt
similarity index 73%
rename from packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/data/StatusBarPhoneDataLayerModule.kt
index 9b0c3fa..9645c69 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/data/repository/CommonRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/StatusBarPhoneDataLayerModule.kt
@@ -13,13 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.systemui.statusbar.phone.data
 
-package com.android.systemui.common.ui.data.repository
-
-import dagger.Binds
+import com.android.systemui.statusbar.phone.data.repository.DarkIconRepositoryModule
 import dagger.Module
 
-@Module
-interface CommonRepositoryModule {
-    @Binds fun bindRepository(impl: ConfigurationRepositoryImpl): ConfigurationRepository
-}
+@Module(includes = [DarkIconRepositoryModule::class]) object StatusBarPhoneDataLayerModule
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt
new file mode 100644
index 0000000..ba377497
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+/** Dark-mode state for tinting icons. */
+interface DarkIconRepository {
+    val darkState: StateFlow<DarkChange>
+}
+
+@SysUISingleton
+class DarkIconRepositoryImpl
+@Inject
+constructor(
+    darkIconDispatcher: SysuiDarkIconDispatcher,
+) : DarkIconRepository {
+    override val darkState: StateFlow<DarkChange> = darkIconDispatcher.darkChangeFlow()
+}
+
+@Module
+interface DarkIconRepositoryModule {
+    @Binds fun bindImpl(impl: DarkIconRepositoryImpl): DarkIconRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/DarkIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/DarkIconInteractor.kt
new file mode 100644
index 0000000..246645e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/DarkIconInteractor.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone.domain.interactor
+
+import android.graphics.Rect
+import com.android.systemui.statusbar.phone.data.repository.DarkIconRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** States pertaining to calculating colors for icons in dark mode. */
+class DarkIconInteractor @Inject constructor(repository: DarkIconRepository) {
+    /** @see com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange.areas */
+    val tintAreas: Flow<Collection<Rect>> = repository.darkState.map { it.areas }
+    /**
+     * @see com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange.darkIntensity
+     */
+    val darkIntensity: Flow<Float> = repository.darkState.map { it.darkIntensity }
+    /** @see com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange.tint */
+    val tintColor: Flow<Int> = repository.darkState.map { it.tint }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationControllerExt.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationControllerExt.kt
index 21acfb4..0a2bbe5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationControllerExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationControllerExt.kt
@@ -13,7 +13,8 @@
  */
 package com.android.systemui.statusbar.policy
 
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import android.content.res.Configuration
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 
@@ -23,14 +24,47 @@
  * @see ConfigurationController.ConfigurationListener.onDensityOrFontScaleChanged
  */
 val ConfigurationController.onDensityOrFontScaleChanged: Flow<Unit>
-    get() =
-        ConflatedCallbackFlow.conflatedCallbackFlow {
-            val listener =
-                object : ConfigurationController.ConfigurationListener {
-                    override fun onDensityOrFontScaleChanged() {
-                        trySend(Unit)
-                    }
+    get() = conflatedCallbackFlow {
+        val listener =
+            object : ConfigurationController.ConfigurationListener {
+                override fun onDensityOrFontScaleChanged() {
+                    trySend(Unit)
                 }
-            addCallback(listener)
-            awaitClose { removeCallback(listener) }
-        }
+            }
+        addCallback(listener)
+        awaitClose { removeCallback(listener) }
+    }
+
+/**
+ * A [Flow] that emits whenever the theme has changed.
+ *
+ * @see ConfigurationController.ConfigurationListener.onThemeChanged
+ */
+val ConfigurationController.onThemeChanged: Flow<Unit>
+    get() = conflatedCallbackFlow {
+        val listener =
+            object : ConfigurationController.ConfigurationListener {
+                override fun onThemeChanged() {
+                    trySend(Unit)
+                }
+            }
+        addCallback(listener)
+        awaitClose { removeCallback(listener) }
+    }
+
+/**
+ * A [Flow] that emits whenever the configuration has changed.
+ *
+ * @see ConfigurationController.ConfigurationListener.onConfigChanged
+ */
+val ConfigurationController.onConfigChanged: Flow<Configuration>
+    get() = conflatedCallbackFlow {
+        val listener =
+            object : ConfigurationController.ConfigurationListener {
+                override fun onConfigChanged(newConfig: Configuration) {
+                    trySend(newConfig)
+                }
+            }
+        addCallback(listener)
+        awaitClose { removeCallback(listener) }
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
index 0a44bda..f0c7be6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
@@ -4,27 +4,74 @@
 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.dagger.qualifiers.Tracing
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.util.TraceUtils.Companion.coroutineTracingIsEnabled
+import com.android.systemui.util.tracing.TraceContextElement
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import javax.inject.Qualifier
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
+
+/** Key associated with a [Boolean] flag that enables or disables the coroutine tracing feature. */
+@Qualifier
+annotation class CoroutineTracingEnabledKey
+
+/**
+ * Same as [@Application], but does not make use of flags. This should only be used when early usage
+ * of [@Application] would introduce a circular dependency on [FeatureFlagsClassic].
+ */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class UnflaggedApplication
+
+/**
+ * Same as [@Background], but does not make use of flags. This should only be used when early usage
+ * of [@Application] would introduce a circular dependency on [FeatureFlagsClassic].
+ */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class UnflaggedBackground
 
 /** Providers for various coroutines-related constructs. */
 @Module
-object CoroutinesModule {
+class CoroutinesModule {
     @Provides
     @SysUISingleton
     @Application
     fun applicationScope(
-        @Main dispatcher: CoroutineDispatcher,
-    ): CoroutineScope = CoroutineScope(dispatcher)
+            @Main dispatcherContext: CoroutineContext,
+    ): CoroutineScope = CoroutineScope(dispatcherContext)
+
+    @Provides
+    @SysUISingleton
+    @UnflaggedApplication
+    fun unflaggedApplicationScope(): CoroutineScope = CoroutineScope(Dispatchers.Main.immediate)
 
     @Provides
     @SysUISingleton
     @Main
+    @Deprecated(
+        "Use @Main CoroutineContext instead",
+        ReplaceWith("mainCoroutineContext()", "kotlin.coroutines.CoroutineContext")
+    )
     fun mainDispatcher(): CoroutineDispatcher = Dispatchers.Main.immediate
 
+    @Provides
+    @SysUISingleton
+    @Main
+    fun mainCoroutineContext(@Tracing tracingCoroutineContext: CoroutineContext): CoroutineContext {
+        return Dispatchers.Main.immediate + tracingCoroutineContext
+    }
+
     /**
      * Provide a [CoroutineDispatcher] backed by a thread pool containing at most X threads, where
      * X is the number of CPU cores available.
@@ -37,5 +84,42 @@
     @Provides
     @SysUISingleton
     @Background
+    @Deprecated(
+        "Use @Background CoroutineContext instead",
+        ReplaceWith("bgCoroutineContext()", "kotlin.coroutines.CoroutineContext")
+    )
     fun bgDispatcher(): CoroutineDispatcher = Dispatchers.IO
+
+
+    @Provides
+    @Background
+    @SysUISingleton
+    fun bgCoroutineContext(@Tracing tracingCoroutineContext: CoroutineContext): CoroutineContext {
+        return Dispatchers.IO + tracingCoroutineContext
+    }
+
+    @Provides
+    @UnflaggedBackground
+    @SysUISingleton
+    fun unflaggedBackgroundCoroutineContext(): CoroutineContext {
+        return Dispatchers.IO
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Provides
+    @Tracing
+    @SysUISingleton
+    fun tracingCoroutineContext(
+        @CoroutineTracingEnabledKey enableTracing: Boolean
+    ): CoroutineContext = if (enableTracing) TraceContextElement() else EmptyCoroutineContext
+
+    companion object {
+        @[Provides CoroutineTracingEnabledKey]
+        fun provideIsCoroutineTracingEnabledKey(featureFlags: FeatureFlagsClassic): Boolean {
+            return if (featureFlags.isEnabled(Flags.COROUTINE_TRACING)) {
+                coroutineTracingIsEnabled = true
+                true
+            } else false
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt
new file mode 100644
index 0000000..909a18be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/DisposableHandleExt.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import com.android.systemui.lifecycle.repeatWhenAttached
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.awaitCancellation
+
+/**
+ * Suspends to keep getting updates until cancellation. Once cancelled, mark this as eligible for
+ * garbage collection.
+ *
+ * This utility is useful if you want to bind a [repeatWhenAttached] invocation to the lifetime of a
+ * coroutine, such that cancelling the coroutine cleans up the handle. For example:
+ * ```
+ * myFlow.collectLatest { value ->
+ *     val disposableHandle = myView.repeatWhenAttached { doStuff() }
+ *     doSomethingWith(value)
+ *     // un-bind when done
+ *     disposableHandle.awaitCancellationThenDispose()
+ * }
+ * ```
+ */
+suspend fun DisposableHandle.awaitCancellationThenDispose() {
+    try {
+        awaitCancellation()
+    } finally {
+        dispose()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
index b3834f5..8fe57e11 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
@@ -61,10 +61,10 @@
  *
  * Useful for code that needs to compare the current value to the previous value.
  */
-fun <T, R> Flow<T>.pairwiseBy(
-    initialValue: T,
-    transform: suspend (previousValue: T, newValue: T) -> R,
-): Flow<R> = onStart { emit(initialValue) }.pairwiseBy(transform)
+fun <S, T : S, R> Flow<T>.pairwiseBy(
+    initialValue: S,
+    transform: suspend (previousValue: S, newValue: T) -> R,
+): Flow<R> = pairwiseBy(getInitialValue = { initialValue }, transform)
 
 /**
  * Returns a new [Flow] that combines the two most recent emissions from [this] using [transform].
@@ -75,10 +75,16 @@
  *
  * Useful for code that needs to compare the current value to the previous value.
  */
-fun <T, R> Flow<T>.pairwiseBy(
-    getInitialValue: suspend () -> T,
-    transform: suspend (previousValue: T, newValue: T) -> R,
-): Flow<R> = onStart { emit(getInitialValue()) }.pairwiseBy(transform)
+fun <S, T : S, R> Flow<T>.pairwiseBy(
+    getInitialValue: suspend () -> S,
+    transform: suspend (previousValue: S, newValue: T) -> R,
+): Flow<R> = flow {
+    var previousValue: S = getInitialValue()
+    collect { newVal ->
+        emit(transform(previousValue, newVal))
+        previousValue = newVal
+    }
+}
 
 /**
  * Returns a new [Flow] that produces the two most recent emissions from [this]. Note that the new
@@ -86,7 +92,7 @@
  *
  * Useful for code that needs to compare the current value to the previous value.
  */
-fun <T> Flow<T>.pairwise(): Flow<WithPrev<T>> = pairwiseBy(::WithPrev)
+fun <T> Flow<T>.pairwise(): Flow<WithPrev<T, T>> = pairwiseBy(::WithPrev)
 
 /**
  * Returns a new [Flow] that produces the two most recent emissions from [this]. [initialValue] will
@@ -94,10 +100,11 @@
  *
  * Useful for code that needs to compare the current value to the previous value.
  */
-fun <T> Flow<T>.pairwise(initialValue: T): Flow<WithPrev<T>> = pairwiseBy(initialValue, ::WithPrev)
+fun <S, T : S> Flow<T>.pairwise(initialValue: S): Flow<WithPrev<S, T>> =
+    pairwiseBy(initialValue, ::WithPrev)
 
 /** Holds a [newValue] emitted from a [Flow], along with the [previousValue] emitted value. */
-data class WithPrev<T>(val previousValue: T, val newValue: T)
+data class WithPrev<out S, out T : S>(val previousValue: S, val newValue: T)
 
 /**
  * Returns a new [Flow] that combines the [Set] changes between each emission from [this] using
@@ -265,112 +272,127 @@
  * immediately invoke [getValue] to establish its initial value.
  */
 inline fun <T> CoroutineScope.stateFlow(
-    changedSignals: Flow<Unit>,
+    changedSignals: Flow<*>,
     crossinline getValue: () -> T,
 ): StateFlow<T> =
     changedSignals.map { getValue() }.stateIn(this, SharingStarted.Eagerly, getValue())
 
 inline fun <T1, T2, T3, T4, T5, T6, R> combine(
-        flow: Flow<T1>,
-        flow2: Flow<T2>,
-        flow3: Flow<T3>,
-        flow4: Flow<T4>,
-        flow5: Flow<T5>,
-        flow6: Flow<T6>,
-        crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R
+    flow: Flow<T1>,
+    flow2: Flow<T2>,
+    flow3: Flow<T3>,
+    flow4: Flow<T4>,
+    flow5: Flow<T5>,
+    flow6: Flow<T6>,
+    crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R
 ): Flow<R> {
-    return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6) {
-        args: Array<*> ->
+    return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6) { args: Array<*>
+        ->
         @Suppress("UNCHECKED_CAST")
         transform(
-                args[0] as T1,
-                args[1] as T2,
-                args[2] as T3,
-                args[3] as T4,
-                args[4] as T5,
-                args[5] as T6
+            args[0] as T1,
+            args[1] as T2,
+            args[2] as T3,
+            args[3] as T4,
+            args[4] as T5,
+            args[5] as T6
         )
     }
 }
 
 inline fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
-        flow: Flow<T1>,
-        flow2: Flow<T2>,
-        flow3: Flow<T3>,
-        flow4: Flow<T4>,
-        flow5: Flow<T5>,
-        flow6: Flow<T6>,
-        flow7: Flow<T7>,
-        crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R
+    flow: Flow<T1>,
+    flow2: Flow<T2>,
+    flow3: Flow<T3>,
+    flow4: Flow<T4>,
+    flow5: Flow<T5>,
+    flow6: Flow<T6>,
+    flow7: Flow<T7>,
+    crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R
 ): Flow<R> {
     return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7) {
         args: Array<*> ->
         @Suppress("UNCHECKED_CAST")
         transform(
-                args[0] as T1,
-                args[1] as T2,
-                args[2] as T3,
-                args[3] as T4,
-                args[4] as T5,
-                args[5] as T6,
-                args[6] as T7
+            args[0] as T1,
+            args[1] as T2,
+            args[2] as T3,
+            args[3] as T4,
+            args[4] as T5,
+            args[5] as T6,
+            args[6] as T7
         )
     }
 }
 
 inline fun <T1, T2, T3, T4, T5, T6, T7, T8, R> combine(
-        flow: Flow<T1>,
-        flow2: Flow<T2>,
-        flow3: Flow<T3>,
-        flow4: Flow<T4>,
-        flow5: Flow<T5>,
-        flow6: Flow<T6>,
-        flow7: Flow<T7>,
-        flow8: Flow<T8>,
-        crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R
+    flow: Flow<T1>,
+    flow2: Flow<T2>,
+    flow3: Flow<T3>,
+    flow4: Flow<T4>,
+    flow5: Flow<T5>,
+    flow6: Flow<T6>,
+    flow7: Flow<T7>,
+    flow8: Flow<T8>,
+    crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R
 ): Flow<R> {
     return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8) {
         args: Array<*> ->
         @Suppress("UNCHECKED_CAST")
         transform(
-                args[0] as T1,
-                args[1] as T2,
-                args[2] as T3,
-                args[3] as T4,
-                args[4] as T5,
-                args[5] as T6,
-                args[6] as T7,
-                args[7] as T8
+            args[0] as T1,
+            args[1] as T2,
+            args[2] as T3,
+            args[3] as T4,
+            args[4] as T5,
+            args[5] as T6,
+            args[6] as T7,
+            args[7] as T8
         )
     }
 }
 
 inline fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> combine(
-        flow: Flow<T1>,
-        flow2: Flow<T2>,
-        flow3: Flow<T3>,
-        flow4: Flow<T4>,
-        flow5: Flow<T5>,
-        flow6: Flow<T6>,
-        flow7: Flow<T7>,
-        flow8: Flow<T8>,
-        flow9: Flow<T9>,
-        crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R
+    flow: Flow<T1>,
+    flow2: Flow<T2>,
+    flow3: Flow<T3>,
+    flow4: Flow<T4>,
+    flow5: Flow<T5>,
+    flow6: Flow<T6>,
+    flow7: Flow<T7>,
+    flow8: Flow<T8>,
+    flow9: Flow<T9>,
+    crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R
 ): Flow<R> {
     return kotlinx.coroutines.flow.combine(
-        flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9
+        flow,
+        flow2,
+        flow3,
+        flow4,
+        flow5,
+        flow6,
+        flow7,
+        flow8,
+        flow9
     ) { args: Array<*> ->
         @Suppress("UNCHECKED_CAST")
         transform(
-                args[0] as T1,
-                args[1] as T2,
-                args[2] as T3,
-                args[3] as T4,
-                args[4] as T5,
-                args[5] as T6,
-                args[6] as T7,
-                args[6] as T8,
-                args[6] as T9,
+            args[0] as T1,
+            args[1] as T2,
+            args[2] as T3,
+            args[3] as T4,
+            args[4] as T5,
+            args[5] as T6,
+            args[6] as T7,
+            args[6] as T8,
+            args[6] as T9,
         )
     }
-}
\ No newline at end of file
+}
+
+/**
+ * Returns a [Flow] that immediately emits [Unit] when started, then emits from the given upstream
+ * [Flow] as normal.
+ */
+@Suppress("NOTHING_TO_INLINE")
+inline fun Flow<Unit>.emitOnStart(): Flow<Unit> = onStart { emit(Unit) }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/MapUtils.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/MapUtils.kt
new file mode 100644
index 0000000..41cd95b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/MapUtils.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.util.kotlin
+
+/** Like [mapValues], but discards `null` values returned from [block]. */
+fun <K, V, R> Map<K, V>.mapValuesNotNull(block: (Map.Entry<K, V>) -> R?): Map<K, R> = buildMap {
+    this@mapValuesNotNull.mapValuesNotNullTo(this, block)
+}
+
+/** Like [mapValuesTo], but discards `null` values returned from [block]. */
+fun <K, V, R, M : MutableMap<in K, in R>> Map<out K, V>.mapValuesNotNullTo(
+    destination: M,
+    block: (Map.Entry<K, V>) -> R?,
+): M {
+    for (entry in this) {
+        block(entry)?.also { destination.put(entry.key, it) }
+    }
+    return destination
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/view/LayoutInflaterExt.kt b/packages/SystemUI/src/com/android/systemui/util/view/LayoutInflaterExt.kt
new file mode 100644
index 0000000..6d45d23
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/view/LayoutInflaterExt.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.view
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.util.kotlin.awaitCancellationThenDispose
+import com.android.systemui.util.kotlin.stateFlow
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collectLatest
+
+/**
+ * Perform an inflation right away, then re-inflate whenever the [flow] emits, and call [onInflate]
+ * on the resulting view each time. Dispose of the [DisposableHandle] returned by [onInflate] when
+ * done.
+ *
+ * This never completes unless cancelled, it just suspends and waits for updates.
+ *
+ * For parameters [resource], [root] and [attachToRoot], see [LayoutInflater.inflate].
+ *
+ * An example use-case of this is when a view needs to be re-inflated whenever a configuration
+ * change occurs, which would require the ViewBinder to then re-bind the new view. For example, the
+ * code in the parent view's binder would look like:
+ * ```
+ * parentView.repeatWhenAttached {
+ *     LayoutInflater.from(parentView.context)
+ *         .reinflateOnChange(
+ *             R.layout.my_layout,
+ *             parentView,
+ *             attachToRoot = false,
+ *             coroutineScope = lifecycleScope,
+ *             configurationController.onThemeChanged,
+ *             ),
+ *     ) { view ->
+ *         ChildViewBinder.bind(view as ChildView, childViewModel)
+ *     }
+ * }
+ * ```
+ *
+ * In turn, the bind method (passed through [onInflate]) uses [repeatWhenAttached], which returns a
+ * [DisposableHandle].
+ */
+suspend fun LayoutInflater.reinflateAndBindLatest(
+    resource: Int,
+    root: ViewGroup?,
+    attachToRoot: Boolean,
+    flow: Flow<Unit>,
+    onInflate: (View) -> DisposableHandle?,
+) = coroutineScope {
+    val viewFlow: Flow<View> = stateFlow(flow) { inflate(resource, root, attachToRoot) }
+    viewFlow.bindLatest(onInflate)
+}
+
+/**
+ * Use the [bind] method to bind the view every time this flow emits, and suspend to await for more
+ * updates. New emissions lead to the previous binding call being cancelled if not completed.
+ * Dispose of the [DisposableHandle] returned by [bind] when done.
+ */
+suspend fun Flow<View>.bindLatest(bind: (View) -> DisposableHandle?) {
+    this.collectLatest { view ->
+        val disposableHandle = bind(view)
+        disposableHandle?.awaitCancellationThenDispose()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/SysUITestModule.kt b/packages/SystemUI/tests/src/com/android/SysUITestModule.kt
index 0b3c3b4..c4b43e1 100644
--- a/packages/SystemUI/tests/src/com/android/SysUITestModule.kt
+++ b/packages/SystemUI/tests/src/com/android/SysUITestModule.kt
@@ -17,11 +17,16 @@
 
 import android.content.Context
 import android.content.res.Resources
+import android.testing.TestableContext
+import android.testing.TestableResources
 import com.android.systemui.FakeSystemUiModule
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
 import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.broadcast.FakeBroadcastDispatcher
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 
@@ -33,15 +38,29 @@
             FakeSystemUiModule::class,
         ]
 )
-class SysUITestModule {
-    @Provides fun provideContext(test: SysuiTestCase): Context = test.context
+interface SysUITestModule {
 
-    @Provides @Application fun provideAppContext(test: SysuiTestCase): Context = test.context
+    @Binds fun bindTestableContext(sysuiTestableContext: SysuiTestableContext): TestableContext
+    @Binds fun bindContext(testableContext: TestableContext): Context
+    @Binds @Application fun bindAppContext(context: Context): Context
+    @Binds @Application fun bindAppResources(resources: Resources): Resources
+    @Binds @Main fun bindMainResources(resources: Resources): Resources
+    @Binds fun bindBroadcastDispatcher(fake: FakeBroadcastDispatcher): BroadcastDispatcher
 
-    @Provides @Main
-    fun provideResources(@Application context: Context): Resources = context.resources
+    companion object {
+        @Provides
+        fun provideSysuiTestableContext(test: SysuiTestCase): SysuiTestableContext = test.context
 
-    @Provides
-    fun provideBroadcastDispatcher(test: SysuiTestCase): BroadcastDispatcher =
-        test.fakeBroadcastDispatcher
+        @Provides
+        fun provideTestableResources(context: TestableContext): TestableResources =
+            context.getOrCreateTestableResources()
+
+        @Provides
+        fun provideResources(testableResources: TestableResources): Resources =
+            testableResources.resources
+
+        @Provides
+        fun provideFakeBroadcastDispatcher(test: SysuiTestCase): FakeBroadcastDispatcher =
+            test.fakeBroadcastDispatcher
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
index ff1d5b2..f49ba64 100644
--- a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
+++ b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.NotificationShadeDepthController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
+import com.android.systemui.statusbar.notification.collection.NotifCollection
 import com.android.systemui.statusbar.notification.stack.AmbientState
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
@@ -75,6 +76,7 @@
     @get:Provides val keyguardSecurityModel: KeyguardSecurityModel = mock(),
     @get:Provides val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(),
     @get:Provides val mediaHierarchyManager: MediaHierarchyManager = mock(),
+    @get:Provides val notifCollection: NotifCollection = mock(),
     @get:Provides val notificationListener: NotificationListener = mock(),
     @get:Provides val notificationLockscreenUserManager: NotificationLockscreenUserManager = mock(),
     @get:Provides val notificationMediaManager: NotificationMediaManager = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 22ebd99..f15164e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.animation.ValueAnimator;
@@ -33,8 +34,8 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
@@ -46,13 +47,15 @@
 import androidx.test.filters.LargeTest;
 
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.AnimatorTestRule;
 import com.android.systemui.model.SysUiState;
+import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -61,22 +64,18 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
 @LargeTest
 @RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
 public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
 
+    @Rule
+    public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule();
     private static final float DEFAULT_SCALE = 4.0f;
     private static final float DEFAULT_CENTER_X = 400.0f;
     private static final float DEFAULT_CENTER_Y = 500.0f;
-    // The duration and period couldn't too short, otherwise the ValueAnimator and
-    //    Instrumentation.runOnMainSync won't work in expectation. (b/288926821)
-    private static final long ANIMATION_DURATION_MS = 600;
-    private static final long WAIT_FULL_ANIMATION_PERIOD = 1000;
-    private static final long WAIT_INTERMEDIATE_ANIMATION_PERIOD = 250;
 
     private AtomicReference<Float> mCurrentScale = new AtomicReference<>((float) 0);
     private AtomicReference<Float> mCurrentCenterX = new AtomicReference<>((float) 0);
@@ -105,10 +104,11 @@
     private WindowMagnificationController mSpyController;
     private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
     private Instrumentation mInstrumentation;
-    private long mWaitingAnimationPeriod;
-    private long mWaitIntermediateAnimationPeriod;
+    private long mWaitAnimationDuration;
+    private long mWaitPartialAnimationDuration;
 
     private TestableWindowManager mWindowManager;
+    private ValueAnimator mValueAnimator;
 
     @Before
     public void setUp() throws Exception {
@@ -118,10 +118,14 @@
         mWindowManager = spy(new TestableWindowManager(wm));
         mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
 
-        mWaitingAnimationPeriod = WAIT_FULL_ANIMATION_PERIOD;
-        mWaitIntermediateAnimationPeriod = WAIT_INTERMEDIATE_ANIMATION_PERIOD;
+        // Using the animation duration in WindowMagnificationAnimationController for testing.
+        mWaitAnimationDuration = mContext.getResources()
+                .getInteger(com.android.internal.R.integer.config_longAnimTime);
+        mWaitPartialAnimationDuration = mWaitAnimationDuration / 2;
+
+        mValueAnimator = newValueAnimator();
         mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
-                mContext, newValueAnimator());
+                mContext, mValueAnimator);
         mController = new SpyWindowMagnificationController(mContext, mHandler,
                 mWindowMagnificationAnimationController,
                 mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(),
@@ -131,13 +135,13 @@
 
     @After
     public void tearDown() throws Exception {
-        mInstrumentation.runOnMainSync(() -> mController.deleteWindowMagnification());
+        mController.deleteWindowMagnification();
     }
 
     @Test
     public void enableWindowMagnification_disabled_expectedValuesAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
+        enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -161,16 +165,13 @@
 
     @Test
     public void enableWindowMagnificationWithoutCallback_enabled_expectedValues() {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
+        enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
         final float targetScale = DEFAULT_SCALE + 1.0f;
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                            targetCenterX, targetCenterY, null);
-                });
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, null);
 
         verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
     }
@@ -178,12 +179,8 @@
     @Test
     public void enableWindowMagnificationWithScaleOne_disabled_NoAnimationAndInvokeCallback()
             throws RemoteException {
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mWindowMagnificationAnimationController.enableWindowMagnification(1,
-                            DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationCallback);
-                });
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        mWindowMagnificationAnimationController.enableWindowMagnification(1,
+                DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationCallback);
 
         verify(mSpyController).enableWindowMagnificationInternal(1, DEFAULT_CENTER_X,
                 DEFAULT_CENTER_Y, 0f, 0f);
@@ -193,22 +190,19 @@
     @Test
     public void enableWindowMagnification_enabling_expectedValuesAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
         final float targetScale = DEFAULT_SCALE + 1.0f;
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, mAnimationCallback2);
-            mCurrentScale.set(mController.getScale());
-            mCurrentCenterX.set(mController.getCenterX());
-            mCurrentCenterY.set(mController.getCenterY());
-        });
-
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, mAnimationCallback2);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -226,24 +220,18 @@
 
     @Test
     public void enableWindowMagnificationWithUnchanged_enabling_expectedValuesToDefault()
-            throws InterruptedException {
-        final CountDownLatch countDownLatch = new CountDownLatch(2);
-        final MockMagnificationAnimationCallback animationCallback =
-                new MockMagnificationAnimationCallback(countDownLatch);
+            throws RemoteException {
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
+                mAnimationCallback);
 
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
-                animationCallback);
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
-                            Float.NaN, Float.NaN, animationCallback);
-                });
+        mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
+                Float.NaN, Float.NaN, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
 
-        assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
         // The callback in 2nd enableWindowMagnification will return true
-        assertEquals(1, animationCallback.getSuccessCount());
+        verify(mAnimationCallback2).onResult(true);
         // The callback in 1st enableWindowMagnification will return false
-        assertEquals(1, animationCallback.getFailedCount());
+        verify(mAnimationCallback).onResult(false);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
     }
 
@@ -256,16 +244,13 @@
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, mAnimationCallback);
-            mCurrentScale.set(mController.getScale());
-            mCurrentCenterX.set(mController.getCenterX());
-            mCurrentCenterY.set(mController.getCenterY());
-        });
-
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, mAnimationCallback);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -293,16 +278,13 @@
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, mAnimationCallback);
-            mCurrentScale.set(mController.getScale());
-            mCurrentCenterX.set(mController.getCenterX());
-            mCurrentCenterY.set(mController.getCenterY());
-        });
-
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, mAnimationCallback);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -331,11 +313,9 @@
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, null);
-        });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, null);
 
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
         assertEquals(WindowMagnificationAnimationController.STATE_DISABLED,
@@ -346,17 +326,16 @@
     public void
             enableMagnificationWithoutCallback_enabling_expectedValuesAndInvokeFormerCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
         final float targetScale = DEFAULT_SCALE - 1.0f;
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, null);
-        });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, null);
+
         verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
         verify(mAnimationCallback).onResult(false);
     }
@@ -364,15 +343,13 @@
     @Test
     public void enableWindowMagnificationWithSameSpec_enabling_NoAnimationAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
-                    Float.NaN, Float.NaN, mAnimationCallback2);
-        });
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
+                Float.NaN, Float.NaN, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
@@ -383,28 +360,30 @@
     @Test
     public void enableWindowMagnification_disabling_expectedValuesAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
-        deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationWithoutAnimation();
+        deleteWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
         final float targetScale = DEFAULT_SCALE + 1.0f;
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                            targetCenterX, targetCenterY, mAnimationCallback2);
-                    mCurrentScale.set(mController.getScale());
-                    mCurrentCenterX.set(mController.getCenterX());
-                    mCurrentCenterY.set(mController.getCenterY());
-                });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, mAnimationCallback2);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+
         // Current spec shouldn't match given spec.
         verify(mAnimationCallback2, never()).onResult(anyBoolean());
         verify(mAnimationCallback).onResult(false);
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        // ValueAnimator.reverse() could not work correctly with the AnimatorTestRule since it is
+        // using SystemClock in reverse() (b/305731398). Therefore, we call end() on the animator
+        // directly to verify the result of animation is correct instead of querying the animation
+        // frame at a specific timing.
+        mValueAnimator.end();
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -424,18 +403,15 @@
             enableMagnificationWithoutCallback_disabling_expectedValuesAndInvokeFormerCallback()
             throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
-        deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        deleteWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
         final float targetScale = DEFAULT_SCALE + 1.0f;
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                            targetCenterX, targetCenterY, null);
-                });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, null);
 
         verify(mAnimationCallback).onResult(false);
         verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
@@ -444,16 +420,14 @@
     @Test
     public void enableWindowMagnificationWithSameSpec_disabling_NoAnimationAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
-        deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationWithoutAnimation();
+        deleteWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
-                    Float.NaN, Float.NaN, mAnimationCallback2);
-        });
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
+                Float.NaN, Float.NaN, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
@@ -470,16 +444,13 @@
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
-                    targetCenterX, targetCenterY, mAnimationCallback2);
-            mCurrentScale.set(mController.getScale());
-            mCurrentCenterX.set(mController.getCenterX());
-            mCurrentCenterY.set(mController.getCenterY());
-        });
-
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                targetCenterX, targetCenterY, mAnimationCallback2);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+        advanceTimeBy(mWaitAnimationDuration);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -498,129 +469,110 @@
     public void enableWindowMagnificationWithOffset_expectedValues() {
         final float offsetRatio = -0.1f;
         final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
-        mInstrumentation.runOnMainSync(() -> {
-            Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
-                    windowBounds.exactCenterX(), windowBounds.exactCenterY(),
-                    offsetRatio, offsetRatio, mAnimationCallback);
-        });
-        SystemClock.sleep(mWaitingAnimationPeriod);
-        final View attachedView = mWindowManager.getAttachedView();
-        assertNotNull(attachedView);
-        final Rect mirrorViewBound = new Rect();
-        final View mirrorView = attachedView.findViewById(R.id.surface_view);
-        assertNotNull(mirrorView);
-        mirrorView.getBoundsOnScreen(mirrorViewBound);
 
-        assertEquals((int) (offsetRatio * mirrorViewBound.width() / 2),
-                (int) (mirrorViewBound.exactCenterX() - windowBounds.exactCenterX()));
-        assertEquals((int) (offsetRatio * mirrorViewBound.height() / 2),
-                (int) (mirrorViewBound.exactCenterY() - windowBounds.exactCenterY()));
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+                windowBounds.exactCenterX(), windowBounds.exactCenterY(),
+                offsetRatio, offsetRatio, mAnimationCallback);
+        advanceTimeBy(mWaitAnimationDuration);
 
+        // We delay the time of verifying to wait for the measurement and layout of the view
+        mHandler.postDelayed(() -> {
+            final View attachedView = mWindowManager.getAttachedView();
+            assertNotNull(attachedView);
+            final Rect mirrorViewBound = new Rect();
+            final View mirrorView = attachedView.findViewById(R.id.surface_view);
+            assertNotNull(mirrorView);
+            mirrorView.getBoundsOnScreen(mirrorViewBound);
+
+            assertEquals((int) (offsetRatio * mirrorViewBound.width() / 2),
+                    (int) (mirrorViewBound.exactCenterX() - windowBounds.exactCenterX()));
+            assertEquals((int) (offsetRatio * mirrorViewBound.height() / 2),
+                    (int) (mirrorViewBound.exactCenterY() - windowBounds.exactCenterY()));
+        }, 100);
     }
 
     @Test
-    public void moveWindowMagnifierToPosition_enabled_expectedValues()
-            throws InterruptedException {
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        final MockMagnificationAnimationCallback animationCallback =
-                new MockMagnificationAnimationCallback(countDownLatch);
+    public void moveWindowMagnifierToPosition_enabled_expectedValues() throws RemoteException {
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                    targetCenterX, targetCenterY, animationCallback);
-        });
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                targetCenterX, targetCenterY, mAnimationCallback);
+        advanceTimeBy(mWaitAnimationDuration);
 
-        assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
-        assertEquals(1, animationCallback.getSuccessCount());
-        assertEquals(0, animationCallback.getFailedCount());
+        verify(mAnimationCallback).onResult(true);
+        verify(mAnimationCallback, never()).onResult(false);
         verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
     }
 
     @Test
     public void moveWindowMagnifierToPositionMultipleTimes_enabled_expectedValuesToLastOne()
-            throws InterruptedException {
-        final CountDownLatch countDownLatch = new CountDownLatch(4);
-        final MockMagnificationAnimationCallback animationCallback =
-                new MockMagnificationAnimationCallback(countDownLatch);
+            throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                    DEFAULT_CENTER_X + 10, DEFAULT_CENTER_Y + 10, animationCallback);
-            mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                    DEFAULT_CENTER_X + 20, DEFAULT_CENTER_Y + 20, animationCallback);
-            mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                    DEFAULT_CENTER_X + 30, DEFAULT_CENTER_Y + 30, animationCallback);
-            mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                    DEFAULT_CENTER_X + 40, DEFAULT_CENTER_Y + 40, animationCallback);
-        });
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                DEFAULT_CENTER_X + 10, DEFAULT_CENTER_Y + 10, mAnimationCallback);
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                DEFAULT_CENTER_X + 20, DEFAULT_CENTER_Y + 20, mAnimationCallback);
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                DEFAULT_CENTER_X + 30, DEFAULT_CENTER_Y + 30, mAnimationCallback);
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                DEFAULT_CENTER_X + 40, DEFAULT_CENTER_Y + 40, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
 
-        assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
         // only the last one callback will return true
-        assertEquals(1, animationCallback.getSuccessCount());
+        verify(mAnimationCallback2).onResult(true);
         // the others will return false
-        assertEquals(3, animationCallback.getFailedCount());
+        verify(mAnimationCallback, times(3)).onResult(false);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 40, DEFAULT_CENTER_Y + 40);
     }
 
     @Test
     public void moveWindowMagnifierToPosition_enabling_expectedValuesToLastOne()
-            throws InterruptedException {
-        final CountDownLatch countDownLatch = new CountDownLatch(2);
-        final MockMagnificationAnimationCallback animationCallback =
-                new MockMagnificationAnimationCallback(countDownLatch);
+            throws RemoteException {
         final float targetCenterX = DEFAULT_CENTER_X + 100;
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
-                animationCallback);
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                            targetCenterX, targetCenterY, animationCallback);
-                });
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
+                mAnimationCallback);
 
-        assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                targetCenterX, targetCenterY, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
+
         // The callback in moveWindowMagnifierToPosition will return true
-        assertEquals(1, animationCallback.getSuccessCount());
+        verify(mAnimationCallback2).onResult(true);
         // The callback in enableWindowMagnification will return false
-        assertEquals(1, animationCallback.getFailedCount());
+        verify(mAnimationCallback).onResult(false);
         verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
     }
 
     @Test
     public void moveWindowMagnifierToPositionWithCenterUnchanged_enabling_expectedValuesToDefault()
-            throws InterruptedException {
-        final CountDownLatch countDownLatch = new CountDownLatch(2);
-        final MockMagnificationAnimationCallback animationCallback =
-                new MockMagnificationAnimationCallback(countDownLatch);
+            throws RemoteException {
 
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
-                animationCallback);
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
-                            Float.NaN, Float.NaN, animationCallback);
-                });
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
+                mAnimationCallback);
 
-        assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
+        mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
+                Float.NaN, Float.NaN, mAnimationCallback2);
+        advanceTimeBy(mWaitAnimationDuration);
+
         // The callback in moveWindowMagnifierToPosition will return true
-        assertEquals(1, animationCallback.getSuccessCount());
+        verify(mAnimationCallback2).onResult(true);
         // The callback in enableWindowMagnification will return false
-        assertEquals(1, animationCallback.getFailedCount());
+        verify(mAnimationCallback).onResult(false);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
     }
 
     @Test
     public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
+        enableWindowMagnificationWithoutAnimation();
 
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
+        enableWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
         verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
@@ -632,7 +584,7 @@
             throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
 
-        deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
+        deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
         verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
@@ -659,7 +611,7 @@
     @Test
     public void deleteWindowMagnification_disabled_doNothingAndInvokeCallback()
             throws RemoteException {
-        deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
+        deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback);
 
         Mockito.verifyNoMoreInteractions(mSpyController);
         verify(mAnimationCallback).onResult(true);
@@ -668,20 +620,23 @@
     @Test
     public void deleteWindowMagnification_enabling_expectedValuesAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.deleteWindowMagnification(
-                            mAnimationCallback2);
-                    mCurrentScale.set(mController.getScale());
-                    mCurrentCenterX.set(mController.getCenterX());
-                    mCurrentCenterY.set(mController.getCenterY());
-                });
-        SystemClock.sleep(mWaitingAnimationPeriod);
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.deleteWindowMagnification(
+                mAnimationCallback2);
+        mCurrentScale.set(mController.getScale());
+        mCurrentCenterX.set(mController.getCenterX());
+        mCurrentCenterY.set(mController.getCenterY());
+        // ValueAnimator.reverse() could not work correctly with the AnimatorTestRule since it is
+        // using SystemClock in reverse() (b/305731398). Therefore, we call end() on the animator
+        // directly to verify the result of animation is correct instead of querying the animation
+        // frame at a specific timing.
+        mValueAnimator.end();
+
+        verify(mSpyController).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -702,14 +657,11 @@
     @Test
     public void deleteWindowMagnificationWithoutCallback_enabling_expectedValuesAndInvokeCallback()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.deleteWindowMagnification(null);
-                });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.deleteWindowMagnification(null);
 
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
         verify(mAnimationCallback).onResult(false);
@@ -717,13 +669,13 @@
 
     @Test
     public void deleteWindowMagnification_disabling_checkStartAndValues() throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
-        deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationWithoutAnimation();
+        deleteWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback2);
+        deleteWindowMagnificationAndWaitAnimating(mWaitAnimationDuration, mAnimationCallback2);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+        verify(mSpyController).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
                 mCenterXCaptor.capture(), mCenterYCaptor.capture(),
                 mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
@@ -738,8 +690,8 @@
     @Test
     public void deleteWindowMagnificationWithoutCallback_disabling_checkStartAndValues()
             throws RemoteException {
-        enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
-        deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
+        enableWindowMagnificationWithoutAnimation();
+        deleteWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
         deleteWindowMagnificationAndWaitAnimating(0, null);
@@ -757,9 +709,9 @@
         final float offsetX = 50.0f;
         final float offsetY =
                 (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
-                + 1.0f;
-        mInstrumentation.runOnMainSync(
-                () -> mController.moveWindowMagnifier(offsetX, offsetY));
+                        + 1.0f;
+
+        mController.moveWindowMagnifier(offsetX, offsetY);
 
         verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y + offsetY);
@@ -774,8 +726,8 @@
         final float offsetY =
                 (float) Math.floor(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
                         - 1.0f;
-        mInstrumentation.runOnMainSync(
-                () -> mController.moveWindowMagnifier(offsetX, offsetY));
+
+        mController.moveWindowMagnifier(offsetX, offsetY);
 
         verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y);
@@ -790,11 +742,8 @@
                 (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE);
         // while diagonal scrolling enabled,
         //  should move with both offsetX and offsetY without regrading offsetY/offsetX
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    mController.setDiagonalScrolling(true);
-                    mController.moveWindowMagnifier(offsetX, offsetY);
-                });
+        mController.setDiagonalScrolling(true);
+        mController.moveWindowMagnifier(offsetX, offsetY);
 
         verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y + offsetY);
@@ -806,14 +755,17 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(
-                () -> mController.moveWindowMagnifierToPosition(targetCenterX, targetCenterY,
-                        mAnimationCallback));
-        SystemClock.sleep(mWaitingAnimationPeriod);
+        mController.moveWindowMagnifierToPosition(targetCenterX, targetCenterY,
+                mAnimationCallback);
+        advanceTimeBy(mWaitAnimationDuration);
 
         verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
     }
 
+    private void advanceTimeBy(long timeDelta) {
+        mAnimatorTestRule.advanceTimeBy(timeDelta);
+    }
+
     private void verifyFinalSpec(float expectedScale, float expectedCenterX,
             float expectedCenterY) {
         assertEquals(expectedScale, mController.getScale(), 0f);
@@ -822,33 +774,24 @@
     }
 
     private void enableWindowMagnificationWithoutAnimation() {
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
-                            DEFAULT_CENTER_X, DEFAULT_CENTER_Y, null);
-                });
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+                DEFAULT_CENTER_X, DEFAULT_CENTER_Y, null);
     }
 
     private void enableWindowMagnificationAndWaitAnimating(long duration,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    Mockito.reset(mSpyController);
-                    mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
-                            DEFAULT_CENTER_X, DEFAULT_CENTER_Y, callback);
-                });
-        SystemClock.sleep(duration);
+        Mockito.reset(mSpyController);
+        mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+                DEFAULT_CENTER_X, DEFAULT_CENTER_Y, callback);
+        advanceTimeBy(duration);
     }
 
     private void deleteWindowMagnificationAndWaitAnimating(long duration,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        mInstrumentation.runOnMainSync(
-                () -> {
-                    resetMockObjects();
-                    mWindowMagnificationAnimationController.deleteWindowMagnification(callback);
-                });
-        SystemClock.sleep(duration);
+        resetMockObjects();
+        mWindowMagnificationAnimationController.deleteWindowMagnification(callback);
+        advanceTimeBy(duration);
     }
 
     private void verifyStartValue(ArgumentCaptor<Float> captor, float startValue) {
@@ -937,9 +880,9 @@
         }
     }
 
-    private static ValueAnimator newValueAnimator() {
+    private ValueAnimator newValueAnimator() {
         final ValueAnimator valueAnimator = new ValueAnimator();
-        valueAnimator.setDuration(ANIMATION_DURATION_MS);
+        valueAnimator.setDuration(mWaitAnimationDuration);
         valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f));
         valueAnimator.setFloatValues(0.0f, 1.0f);
         return valueAnimator;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index df7d1b7..aed795a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -222,14 +222,14 @@
 
     @Test
     public void showingImeInsetsChange_overlapOnIme_menuShownAboveIme() {
-        final float menuTop = IME_TOP + 100;
-        mMenuAnimationController.moveAndPersistPosition(new PointF(0, menuTop));
+        mMenuAnimationController.moveAndPersistPosition(new PointF(0, IME_TOP + 100));
+        final PointF beforePosition = mMenuView.getMenuPosition();
 
         dispatchShowingImeInsets();
 
         final float menuBottom = mMenuView.getTranslationY() + mMenuView.getMenuHeight();
-        assertThat(mMenuView.getTranslationX()).isEqualTo(0);
-        assertThat(menuBottom).isLessThan(IME_TOP);
+        assertThat(mMenuView.getTranslationX()).isEqualTo(beforePosition.x);
+        assertThat(menuBottom).isLessThan(beforePosition.y);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
index 0e14591..52c6e22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
@@ -18,9 +18,11 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -61,80 +63,70 @@
     @Test
     fun restart_ImmediatelySatisfied() =
         testScope.runTest {
-            conditionA.canRestart = true
-            conditionB.canRestart = true
+            conditionA.canRestart.emit(true)
+            conditionB.canRestart.emit(true)
             restarter.restartSystemUI("Restart for test")
-            advanceUntilIdle()
+            runCurrent()
             verify(systemExitRestarter).restartSystemUI(any())
         }
 
     @Test
     fun restart_WaitsForConditionA() =
         testScope.runTest {
-            conditionA.canRestart = false
-            conditionB.canRestart = true
+            conditionA.canRestart.emit(false)
+            conditionB.canRestart.emit(true)
 
             restarter.restartSystemUI("Restart for test")
-            advanceUntilIdle()
+            runCurrent()
             // No restart occurs yet.
             verify(systemExitRestarter, never()).restartSystemUI(any())
 
-            conditionA.canRestart = true
-            conditionA.retryFn?.invoke()
-            advanceUntilIdle()
+            conditionA.canRestart.emit(true)
+            runCurrent()
             verify(systemExitRestarter).restartSystemUI(any())
         }
 
     @Test
     fun restart_WaitsForConditionB() =
         testScope.runTest {
-            conditionA.canRestart = true
-            conditionB.canRestart = false
+            conditionA.canRestart.emit(true)
+            conditionB.canRestart.emit(false)
 
             restarter.restartSystemUI("Restart for test")
-            advanceUntilIdle()
+            runCurrent()
             // No restart occurs yet.
             verify(systemExitRestarter, never()).restartSystemUI(any())
 
-            conditionB.canRestart = true
-            conditionB.retryFn?.invoke()
-            advanceUntilIdle()
+            conditionB.canRestart.emit(true)
+            runCurrent()
             verify(systemExitRestarter).restartSystemUI(any())
         }
 
     @Test
     fun restart_WaitsForAllConditions() =
         testScope.runTest {
-            conditionA.canRestart = true
-            conditionB.canRestart = false
+            conditionA.canRestart.emit(true)
+            conditionB.canRestart.emit(false)
 
             restarter.restartSystemUI("Restart for test")
-            advanceUntilIdle()
+            runCurrent()
             // No restart occurs yet.
             verify(systemExitRestarter, never()).restartSystemUI(any())
 
             // B becomes true, but A is now false
-            conditionA.canRestart = false
-            conditionB.canRestart = true
-            conditionB.retryFn?.invoke()
-            advanceUntilIdle()
+            conditionA.canRestart.emit(false)
+            conditionB.canRestart.emit(true)
             // No restart occurs yet.
             verify(systemExitRestarter, never()).restartSystemUI(any())
 
-            conditionA.canRestart = true
-            conditionA.retryFn?.invoke()
-            advanceUntilIdle()
+            conditionA.canRestart.emit(true)
+            runCurrent()
             verify(systemExitRestarter).restartSystemUI(any())
         }
 
     class FakeCondition : ConditionalRestarter.Condition {
-        var retryFn: (() -> Unit)? = null
-        var canRestart = false
+        val canRestart = MutableStateFlow(false)
 
-        override fun canRestartNow(retryFn: () -> Unit): Boolean {
-            this.retryFn = retryFn
-
-            return canRestart
-        }
+        override val canRestartNow: Flow<Boolean> = canRestart
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
new file mode 100644
index 0000000..db6f85f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.coroutines.collectLastValue
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+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()!
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class NotOccludedConditionTest : SysuiTestCase() {
+    private lateinit var condition: NotOccludedCondition
+
+    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+    private val transitionValue = MutableStateFlow(0f)
+
+    private val testDispatcher: TestDispatcher = StandardTestDispatcher()
+    private val testScope: TestScope = TestScope(testDispatcher)
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        whenever(keyguardTransitionInteractor.transitionValue(KeyguardState.OCCLUDED))
+            .thenReturn(transitionValue)
+        condition = NotOccludedCondition({ keyguardTransitionInteractor })
+        testScope.runCurrent()
+    }
+
+    @Test
+    fun testCondition_occluded() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
+
+            transitionValue.emit(1f)
+            assertThat(canRestart).isFalse()
+        }
+
+    @Test
+    fun testCondition_notOccluded() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
+
+            transitionValue.emit(0f)
+            assertThat(canRestart).isTrue()
+        }
+
+    @Test
+    fun testCondition_invokesRetry() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
+
+            transitionValue.emit(1f)
+
+            assertThat(canRestart).isFalse()
+
+            transitionValue.emit(0f)
+
+            assertThat(canRestart).isTrue()
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
index 647b05a..7d7abab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
@@ -17,8 +17,13 @@
 
 import android.test.suitebuilder.annotation.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.statusbar.policy.BatteryController
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.mockito.ArgumentCaptor
@@ -35,42 +40,51 @@
     private lateinit var condition: PluggedInCondition
 
     @Mock private lateinit var batteryController: BatteryController
+    private val testDispatcher: TestDispatcher = StandardTestDispatcher()
+    private val testScope: TestScope = TestScope(testDispatcher)
+    private val callbackCaptor =
+        ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        condition = PluggedInCondition(batteryController)
+
+        condition = PluggedInCondition({ batteryController })
     }
 
     @Test
-    fun testCondition_unplugged() {
-        whenever(batteryController.isPluggedIn).thenReturn(false)
+    fun testCondition_unplugged() =
+        testScope.runTest {
+            whenever(batteryController.isPluggedIn).thenReturn(false)
 
-        assertThat(condition.canRestartNow({})).isFalse()
-    }
+            val canRestart by collectLastValue(condition.canRestartNow)
+
+            assertThat(canRestart).isFalse()
+        }
 
     @Test
-    fun testCondition_pluggedIn() {
-        whenever(batteryController.isPluggedIn).thenReturn(true)
+    fun testCondition_pluggedIn() =
+        testScope.runTest {
+            whenever(batteryController.isPluggedIn).thenReturn(true)
 
-        assertThat(condition.canRestartNow({})).isTrue()
-    }
+            val canRestart by collectLastValue(condition.canRestartNow)
+
+            assertThat(canRestart).isTrue()
+        }
 
     @Test
-    fun testCondition_invokesRetry() {
-        whenever(batteryController.isPluggedIn).thenReturn(false)
-        var retried = false
-        val retryFn = { retried = true }
+    fun testCondition_invokesRetry() =
+        testScope.runTest {
+            whenever(batteryController.isPluggedIn).thenReturn(false)
 
-        // No restart yet, but we do register a listener now.
-        assertThat(condition.canRestartNow(retryFn)).isFalse()
-        val captor =
-            ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
-        verify(batteryController).addCallback(captor.capture())
+            val canRestart by collectLastValue(condition.canRestartNow)
 
-        whenever(batteryController.isPluggedIn).thenReturn(true)
+            assertThat(canRestart).isFalse()
 
-        captor.value.onBatteryLevelChanged(0, true, true)
-        assertThat(retried).isTrue()
-    }
+            verify(batteryController).addCallback(callbackCaptor.capture())
+
+            callbackCaptor.value.onBatteryLevelChanged(0, true, false)
+
+            assertThat(canRestart).isTrue()
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
index f7a773e..1f04828 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
@@ -17,15 +17,17 @@
 
 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.coroutines.collectLastValue
+import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
-import org.mockito.ArgumentCaptor
 import org.mockito.Mock
-import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -36,42 +38,50 @@
 class ScreenIdleConditionTest : SysuiTestCase() {
     private lateinit var condition: ScreenIdleCondition
 
-    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock private lateinit var powerInteractor: PowerInteractor
+    private val isAsleep = MutableStateFlow(false)
+
+    private val testDispatcher: TestDispatcher = StandardTestDispatcher()
+    private val testScope: TestScope = TestScope(testDispatcher)
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        condition = ScreenIdleCondition(wakefulnessLifecycle)
+        whenever(powerInteractor.isAsleep).thenReturn(isAsleep)
+        condition = ScreenIdleCondition({ powerInteractor })
     }
 
     @Test
-    fun testCondition_awake() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+    fun testCondition_awake() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
 
-        assertThat(condition.canRestartNow {}).isFalse()
-    }
+            isAsleep.emit(false)
+
+            assertThat(canRestart).isFalse()
+        }
 
     @Test
-    fun testCondition_asleep() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+    fun testCondition_asleep() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
 
-        assertThat(condition.canRestartNow {}).isTrue()
-    }
+            isAsleep.emit(true)
+
+            assertThat(canRestart).isTrue()
+        }
 
     @Test
-    fun testCondition_invokesRetry() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
-        var retried = false
-        val retryFn = { retried = true }
+    fun testCondition_invokesRetry() =
+        testScope.runTest {
+            val canRestart by collectLastValue(condition.canRestartNow)
 
-        // No restart yet, but we do register a listener now.
-        assertThat(condition.canRestartNow(retryFn)).isFalse()
-        val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
-        verify(wakefulnessLifecycle).addObserver(captor.capture())
+            isAsleep.emit(false)
 
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+            assertThat(canRestart).isFalse()
 
-        captor.value.onFinishedGoingToSleep()
-        assertThat(retried).isTrue()
-    }
+            isAsleep.emit(true)
+
+            assertThat(canRestart).isTrue()
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/SetFlagsRuleExtensions.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/SetFlagsRuleExtensions.kt
index bb6786a..e16b8d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/SetFlagsRuleExtensions.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/SetFlagsRuleExtensions.kt
@@ -18,6 +18,17 @@
 
 import android.platform.test.flag.junit.SetFlagsRule
 
+/**
+ * Set the given flag's value to the real value for the current build configuration.
+ * This prevents test code from crashing because it is reading an unspecified flag value.
+ *
+ * REMINDER: You should always test your code with your flag in both configurations, so
+ * generally you should be explicitly enabling or disabling your flag. This method is for
+ * situations where the flag needs to be read (e.g. in the class constructor), but its value
+ * shouldn't affect the actual test cases. In those cases, it's mildly safer to use this method
+ * than to hard-code `false` or `true` because then at least if you're wrong, and the flag value
+ * *does* matter, you'll notice when the flag is flipped and tests start failing.
+ */
 fun SetFlagsRule.setFlagDefault(flagName: String) {
     if (getFlagDefault(flagName)) {
         enableFlags(flagName)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 819d08a..9bb2434 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -43,7 +43,6 @@
 import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED
 import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
 import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
@@ -82,6 +81,7 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.FakeKeyguardStateController
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.user.data.model.SelectionStatus
@@ -94,6 +94,8 @@
 import com.android.systemui.util.time.FakeSystemClock
 import com.android.systemui.util.time.SystemClock
 import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestDispatcher
@@ -116,8 +118,6 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.MockitoAnnotations
-import java.io.PrintWriter
-import java.io.StringWriter
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
@@ -195,9 +195,11 @@
             }
 
         powerRepository = FakePowerRepository()
-        powerInteractor = PowerInteractorFactory.create(
-                repository = powerRepository,
-        ).powerInteractor
+        powerInteractor =
+            PowerInteractorFactory.create(
+                    repository = powerRepository,
+                )
+                .powerInteractor
 
         val withDeps =
             KeyguardInteractorFactory.create(
@@ -210,10 +212,10 @@
 
         keyguardTransitionRepository = FakeKeyguardTransitionRepository()
         keyguardTransitionInteractor =
-                KeyguardTransitionInteractorFactory.create(
-                        scope = testScope.backgroundScope,
-                        repository = keyguardTransitionRepository,
-                        keyguardInteractor = keyguardInteractor,
+            KeyguardTransitionInteractorFactory.create(
+                    scope = testScope.backgroundScope,
+                    repository = keyguardTransitionRepository,
+                    keyguardInteractor = keyguardInteractor,
                 )
                 .keyguardTransitionInteractor
 
@@ -635,11 +637,7 @@
 
     @Test
     fun authenticateDoesNotRunWhenDeviceIsGoingToSleep() =
-        testScope.runTest {
-            testGatingCheckForFaceAuth {
-                powerInteractor.setAsleepForTest()
-            }
-        }
+        testScope.runTest { testGatingCheckForFaceAuth { powerInteractor.setAsleepForTest() } }
 
     @Test
     fun authenticateDoesNotRunWhenSecureCameraIsActive() =
@@ -736,17 +734,21 @@
             allPreconditionsToRunFaceAuthAreTrue()
 
             Log.i("TEST", "started waking")
-            keyguardTransitionRepository.sendTransitionStep(TransitionStep(
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
                     from = KeyguardState.LOCKSCREEN,
                     to = KeyguardState.OFF,
                     transitionState = TransitionState.FINISHED,
-            ))
+                )
+            )
             runCurrent()
-            keyguardTransitionRepository.sendTransitionStep(TransitionStep(
+            keyguardTransitionRepository.sendTransitionStep(
+                TransitionStep(
                     from = KeyguardState.OFF,
                     to = KeyguardState.LOCKSCREEN,
                     transitionState = TransitionState.STARTED,
-            ))
+                )
+            )
             runCurrent()
 
             Log.i("TEST", "sending display off")
@@ -766,11 +768,13 @@
         testScope.runTest {
             testGatingCheckForFaceAuth {
                 powerInteractor.onFinishedWakingUp()
-                keyguardTransitionRepository.sendTransitionStep(TransitionStep(
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
                         from = KeyguardState.OFF,
                         to = KeyguardState.LOCKSCREEN,
                         transitionState = TransitionState.FINISHED,
-                ))
+                    )
+                )
                 runCurrent()
 
                 displayRepository.emit(
@@ -919,11 +923,7 @@
 
     @Test
     fun detectDoesNotRunWhenDeviceSleepingStartingToSleep() =
-        testScope.runTest {
-            testGatingCheckForDetect {
-                powerInteractor.setAsleepForTest()
-            }
-        }
+        testScope.runTest { testGatingCheckForDetect { powerInteractor.setAsleepForTest() } }
 
     @Test
     fun detectDoesNotRunWhenSecureCameraIsActive() =
@@ -1114,6 +1114,32 @@
             biometricSettingsRepository.setIsFaceAuthCurrentlyAllowed(true)
             faceAuthenticateIsCalled()
         }
+    @Test
+    fun authFailedCallAfterAuthLockedOutErrorShouldBeIgnored() =
+        testScope.runTest {
+            initCollectors()
+            allPreconditionsToRunFaceAuthAreTrue()
+            runCurrent()
+            assertThat(canFaceAuthRun()).isTrue()
+
+            underTest.requestAuthenticate(FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED, false)
+            runCurrent()
+
+            faceAuthenticateIsCalled()
+            authenticationCallback.value.onAuthenticationError(
+                FACE_ERROR_LOCKOUT_PERMANENT,
+                "Too many attempts, face not available"
+            )
+
+            val lockoutError = authStatus() as ErrorFaceAuthenticationStatus
+            assertThat(lockedOut()).isTrue()
+            assertThat(lockoutError.isLockoutError()).isTrue()
+
+            authenticationCallback.value.onAuthenticationFailed()
+            runCurrent()
+
+            assertThat(authStatus()).isEqualTo(lockoutError)
+        }
 
     private suspend fun TestScope.testGatingCheckForFaceAuth(
         gatingCheckModifier: suspend () -> Unit
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
index 429aad1..fd1e2c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt
@@ -63,4 +63,22 @@
 
         verify(service).notifyPermissionRequestInitiated(hostUid, METRICS_CREATION_SOURCE_UNKNOWN)
     }
+
+    @Test
+    fun notifyPermissionRequestDisplayed_forwardsToService() {
+        val hostUid = 987
+
+        logger.notifyPermissionRequestDisplayed(hostUid)
+
+        verify(service).notifyPermissionRequestDisplayed(hostUid)
+    }
+
+    @Test
+    fun notifyAppSelectorDisplayed_forwardsToService() {
+        val hostUid = 654
+
+        logger.notifyAppSelectorDisplayed(hostUid)
+
+        verify(service).notifyAppSelectorDisplayed(hostUid)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
index 6cdf4ef..5255f71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
@@ -44,7 +44,7 @@
 
     private val thumbnailLoader = FakeThumbnailLoader()
 
-    private fun createController(isFirstStart: Boolean = true) =
+    private fun createController(isFirstStart: Boolean = true, hostUid: Int = 123) =
         MediaProjectionAppSelectorController(
             taskListProvider,
             view,
@@ -55,7 +55,8 @@
             callerPackageName,
             thumbnailLoader,
             isFirstStart,
-            logger
+            logger,
+            hostUid,
         )
 
     @Before
@@ -212,20 +213,22 @@
 
     @Test
     fun init_firstStart_logsAppSelectorDisplayed() {
-        val controller = createController(isFirstStart = true)
+        val hostUid = 123456789
+        val controller = createController(isFirstStart = true,  hostUid)
 
         controller.init()
 
-        verify(logger).notifyPermissionProgress(STATE_APP_SELECTOR_DISPLAYED)
+        verify(logger).notifyAppSelectorDisplayed(hostUid)
     }
 
     @Test
     fun init_notFirstStart_doesNotLogAppSelectorDisplayed() {
-        val controller = createController(isFirstStart = false)
+        val hostUid = 123456789
+        val controller = createController(isFirstStart = false, hostUid)
 
         controller.init()
 
-        verify(logger, never()).notifyPermissionProgress(STATE_APP_SELECTOR_DISPLAYED)
+        verify(logger, never()).notifyAppSelectorDisplayed(hostUid)
     }
 
     private fun givenCaptureAllowed(isAllow: Boolean) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index ac03073..c6d156f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -52,6 +52,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.res.R;
 import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -96,6 +97,8 @@
     private MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
     @Mock
     private Dialog mPermissionDialogPrompt;
+    @Mock
+    private UserContextProvider mUserContextProvider;
 
     private TestableLooper mTestableLooper;
     private ScreenRecordTile mTile;
@@ -106,6 +109,7 @@
 
         mTestableLooper = TestableLooper.get(this);
 
+        when(mUserContextProvider.getUserContext()).thenReturn(mContext);
         when(mHost.getContext()).thenReturn(mContext);
 
         mTile = new ScreenRecordTile(
@@ -124,7 +128,8 @@
                 mKeyguardStateController,
                 mDialogLaunchAnimator,
                 mPanelInteractor,
-                mMediaProjectionMetricsLogger
+                mMediaProjectionMetricsLogger,
+                mUserContextProvider
         );
 
         mTile.initialize();
@@ -308,7 +313,8 @@
         onDismissAction.getValue().onDismiss();
 
         verify(mPermissionDialogPrompt).show();
-        verify(mMediaProjectionMetricsLogger).notifyPermissionRequestDisplayed();
+        verify(mMediaProjectionMetricsLogger)
+                .notifyPermissionRequestDisplayed(mContext.getUserId());
     }
 
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt
similarity index 89%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt
index 5659f01..95ee3b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt
@@ -32,16 +32,16 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class QSTileIntentUserActionHandlerTest : SysuiTestCase() {
+class QSTileIntentUserInputHandlerTest : SysuiTestCase() {
 
     @Mock private lateinit var activityStarted: ActivityStarter
 
-    lateinit var underTest: QSTileIntentUserActionHandler
+    lateinit var underTest: QSTileIntentUserInputHandler
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        underTest = QSTileIntentUserActionHandler(activityStarted)
+        underTest = QSTileIntentUserInputHandler(activityStarted)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
index 9907278..31d02ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.log.LogBufferFactory
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.pipeline.shared.TileSpec
-import com.android.systemui.qs.tiles.base.interactor.StateUpdateTrigger
 import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import com.android.systemui.util.mockito.any
@@ -144,7 +143,6 @@
     fun testLogStateUpdate() {
         underTest.logStateUpdate(
             TileSpec.create("test_spec"),
-            StateUpdateTrigger.ForceUpdate,
             QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {},
             "test_data",
         )
@@ -152,21 +150,36 @@
         assertThat(logBuffer.getStringBuffer())
             .contains(
                 "tile state update: " +
-                    "trigger=force, " +
-                    "state=[" +
-                    "label=, " +
+                    "state=[label=, " +
                     "state=INACTIVE, " +
                     "s_label=null, " +
                     "cd=null, " +
                     "sd=null, " +
                     "svi=None, " +
                     "enabled=ENABLED, " +
-                    "a11y=null" +
-                    "], " +
+                    "a11y=null], " +
                     "data=test_data"
             )
     }
 
+    @Test
+    fun testLogForceUpdate() {
+        underTest.logForceUpdate(
+            TileSpec.create("test_spec"),
+        )
+
+        assertThat(logBuffer.getStringBuffer()).contains("tile data force update")
+    }
+
+    @Test
+    fun testLogInitialUpdate() {
+        underTest.logInitialRequest(
+            TileSpec.create("test_spec"),
+        )
+
+        assertThat(logBuffer.getStringBuffer()).contains("tile data initial update")
+    }
+
     private fun LogBuffer.getStringBuffer(): String {
         val stringWriter = StringWriter()
         dump(PrintWriter(stringWriter), 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
index 2084aeb..9b85012 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
@@ -29,11 +29,11 @@
 import com.android.systemui.qs.tiles.base.interactor.FakeDisabledByPolicyInteractor
 import com.android.systemui.qs.tiles.base.interactor.FakeQSTileDataInteractor
 import com.android.systemui.qs.tiles.base.interactor.FakeQSTileUserActionInteractor
-import com.android.systemui.qs.tiles.base.interactor.QSTileDataRequest
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
-import com.android.systemui.qs.tiles.base.interactor.StateUpdateTrigger
 import com.android.systemui.qs.tiles.base.logging.QSTileLogger
 import com.android.systemui.qs.tiles.base.viewmodel.BaseQSTileViewModel
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.test.StandardTestDispatcher
@@ -55,6 +55,7 @@
     @Mock private lateinit var qsTileLogger: QSTileLogger
     @Mock private lateinit var qsTileAnalytics: QSTileAnalytics
 
+    private val fakeUserRepository = FakeUserRepository()
     private val fakeQSTileDataInteractor = FakeQSTileDataInteractor<Any>()
     private val fakeQSTileUserActionInteractor = FakeQSTileUserActionInteractor<Any>()
     private val fakeDisabledByPolicyInteractor = FakeDisabledByPolicyInteractor()
@@ -86,7 +87,7 @@
 
             assertThat(fakeQSTileDataInteractor.dataRequests).isNotEmpty()
             assertThat(fakeQSTileDataInteractor.dataRequests.first())
-                .isEqualTo(QSTileDataRequest(1, StateUpdateTrigger.InitialRequest))
+                .isEqualTo(FakeQSTileDataInteractor.DataRequest(1))
         }
 
     private fun createViewModel(
@@ -102,9 +103,11 @@
                     QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {}
             },
             fakeDisabledByPolicyInteractor,
+            fakeUserRepository,
             fakeFalsingManager,
             qsTileAnalytics,
             qsTileLogger,
+            FakeSystemClock(),
             testCoroutineDispatcher,
             scope.backgroundScope,
         )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
index da4dc85..bf12d7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenrecord
 
+import android.content.Intent
 import android.os.UserHandle
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -25,11 +26,13 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity
 import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN
 import com.android.systemui.mediaprojection.permission.SINGLE_APP
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertEquals
@@ -38,6 +41,9 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -62,6 +68,7 @@
             ScreenRecordPermissionDialog(
                 context,
                 UserHandle.of(0),
+                TEST_HOST_UID,
                 controller,
                 starter,
                 userContextProvider,
@@ -105,6 +112,19 @@
     }
 
     @Test
+    fun startClicked_singleAppSelected_passesHostUidToAppSelector() {
+        dialog.show()
+        onSpinnerItemSelected(SINGLE_APP)
+
+        clickOnStart()
+
+        assertExtraPassedToAppSelector(
+            extraKey = MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID,
+            value = TEST_HOST_UID
+        )
+    }
+
+    @Test
     fun showDialog_dialogIsShowing() {
         dialog.show()
 
@@ -133,9 +153,25 @@
         dialog.requireViewById<View>(android.R.id.button2).performClick()
     }
 
+    private fun clickOnStart() {
+        dialog.requireViewById<View>(android.R.id.button1).performClick()
+    }
+
     private fun onSpinnerItemSelected(position: Int) {
         val spinner = dialog.requireViewById<Spinner>(R.id.screen_share_mode_spinner)
         checkNotNull(spinner.onItemSelectedListener)
             .onItemSelected(spinner, mock(), position, /* id= */ 0)
     }
+
+    private fun assertExtraPassedToAppSelector(extraKey: String, value: Int) {
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(starter).startActivity(intentCaptor.capture(), /* dismissShade= */ eq(true))
+
+        val intent = intentCaptor.value
+        assertThat(intent.extras!!.getInt(extraKey)).isEqualTo(value)
+    }
+
+    companion object {
+        private const val TEST_HOST_UID = 12345
+    }
 }
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 da49230..b421e1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -23,7 +23,6 @@
 import android.view.MotionEvent
 import android.view.View
 import android.view.ViewGroup
-import androidx.core.view.contains
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardMessageAreaController
 import com.android.keyguard.KeyguardSecurityContainerController
@@ -31,8 +30,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.FakeFeatureFlagsImpl
-import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.back.domain.interactor.BackActionInteractor
 import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
@@ -47,6 +44,7 @@
 import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.compose.ComposeFacade.isComposeAvailable
 import com.android.systemui.dock.DockManager
@@ -150,6 +148,7 @@
     private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener
     @Mock private lateinit var notificationInsetsController: NotificationInsetsController
     @Mock private lateinit var mCommunalViewModel: CommunalViewModel
+    private lateinit var mCommunalRepository: FakeCommunalRepository
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
     @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
@@ -175,7 +174,6 @@
     private lateinit var testScope: TestScope
 
     private lateinit var featureFlagsClassic: FakeFeatureFlagsClassic
-    private lateinit var featureFlags: FakeFeatureFlagsImpl
 
     @Before
     fun setUp() {
@@ -199,7 +197,7 @@
         featureFlagsClassic.set(MIGRATE_NSSL, false)
         featureFlagsClassic.set(ALTERNATE_BOUNCER_VIEW, false)
 
-        featureFlags = FakeFeatureFlagsImpl()
+        mCommunalRepository = FakeCommunalRepository()
 
         testScope = TestScope()
         fakeClock = FakeSystemClock()
@@ -235,9 +233,9 @@
                 keyguardTransitionInteractor,
                 primaryBouncerToGoneTransitionViewModel,
                 mCommunalViewModel,
+                mCommunalRepository,
                 notificationExpansionRepository,
                 featureFlagsClassic,
-                featureFlags,
                 fakeClock,
                 BouncerMessageInteractor(
                     repository = BouncerMessageRepositoryImpl(),
@@ -499,7 +497,7 @@
             return
         }
 
-        featureFlags.setFlag(FLAG_COMMUNAL_HUB, true)
+        mCommunalRepository.setIsCommunalEnabled(true)
 
         val mockCommunalPlaceholder = mock(View::class.java)
         val fakeViewIndex = 20
@@ -520,7 +518,7 @@
             return
         }
 
-        featureFlags.setFlag(FLAG_COMMUNAL_HUB, false)
+        mCommunalRepository.setIsCommunalEnabled(false)
 
         val mockCommunalPlaceholder = mock(View::class.java)
         val fakeViewIndex = 20
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index c94741f..9c57101 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -28,7 +28,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.FakeFeatureFlagsImpl
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.back.domain.interactor.BackActionInteractor
 import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
@@ -43,6 +42,7 @@
 import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.dock.DockManager
 import com.android.systemui.dump.DumpManager
@@ -145,6 +145,7 @@
         Optional<UnfoldTransitionProgressProvider>
     @Mock private lateinit var notificationInsetsController: NotificationInsetsController
     @Mock private lateinit var mCommunalViewModel: CommunalViewModel
+    private lateinit var mCommunalRepository: FakeCommunalRepository
     @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
     @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
@@ -181,6 +182,8 @@
         whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
             .thenReturn(emptyFlow())
 
+        mCommunalRepository = FakeCommunalRepository()
+
         val featureFlags = FakeFeatureFlags()
         featureFlags.set(Flags.TRACKPAD_GESTURE_COMMON, true)
         featureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false)
@@ -222,9 +225,9 @@
                 keyguardTransitionInteractor,
                 primaryBouncerToGoneTransitionViewModel,
                 mCommunalViewModel,
+                mCommunalRepository,
                 NotificationExpansionRepository(),
                 featureFlags,
-                FakeFeatureFlagsImpl(),
                 FakeSystemClock(),
                 BouncerMessageInteractor(
                     repository = BouncerMessageRepositoryImpl(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index 3412679..2b3fd34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -37,8 +37,12 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository;
+import com.android.systemui.statusbar.domain.interactor.SilentNotificationStatusIconsVisibilityInteractor;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -68,9 +72,14 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
+        featureFlags.setDefault(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR);
         mListener = new NotificationListener(
                 mContext,
+                featureFlags,
                 mNotificationManager,
+                new SilentNotificationStatusIconsVisibilityInteractor(
+                        new NotificationListenerSettingsRepository()),
                 mFakeSystemClock,
                 mFakeExecutor,
                 mPluginManager);
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 546abd4..6c1f537 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
@@ -39,10 +39,10 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
 import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
 import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
 import com.android.systemui.util.mockito.any
@@ -246,7 +246,7 @@
             unseenFilter.onCleanup()
 
             // THEN: The SeenNotificationProvider has been updated to reflect the suppression
-            assertThat(notificationListInteractor.hasFilteredOutSeenNotifications.value).isTrue()
+            assertThat(seenNotificationsInteractor.hasFilteredOutSeenNotifications.value).isTrue()
         }
     }
 
@@ -597,7 +597,8 @@
             FakeSettings().apply {
                 putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1)
             }
-        val notificationListInteractor = NotificationListInteractor(NotificationListRepository())
+        val seenNotificationsInteractor =
+            SeenNotificationsInteractor(ActiveNotificationListRepository())
         val keyguardCoordinator =
             KeyguardCoordinator(
                 testDispatcher,
@@ -610,7 +611,7 @@
                 testScope.backgroundScope,
                 sectionHeaderVisibilityProvider,
                 fakeSettings,
-                notificationListInteractor,
+                seenNotificationsInteractor,
                 statusBarStateController,
             )
         keyguardCoordinator.attach(notifPipeline)
@@ -618,7 +619,7 @@
             KeyguardCoordinatorTestScope(
                     keyguardCoordinator,
                     testScope,
-                    notificationListInteractor,
+                    seenNotificationsInteractor,
                     fakeSettings,
                 )
                 .testBlock()
@@ -628,7 +629,7 @@
     private inner class KeyguardCoordinatorTestScope(
         private val keyguardCoordinator: KeyguardCoordinator,
         private val scope: TestScope,
-        val notificationListInteractor: NotificationListInteractor,
+        val seenNotificationsInteractor: SeenNotificationsInteractor,
         private val fakeSettings: FakeSettings,
     ) : CoroutineScope by scope {
         val testScheduler: TestCoroutineScheduler
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
index 655bd72..a736182 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -19,6 +19,8 @@
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -27,6 +29,7 @@
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
 import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
@@ -37,8 +40,8 @@
 import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations.initMocks
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations.initMocks
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -52,13 +55,23 @@
     @Mock private lateinit var pipeline: NotifPipeline
     @Mock private lateinit var groupExpansionManagerImpl: GroupExpansionManagerImpl
     @Mock private lateinit var notificationIconAreaController: NotificationIconAreaController
+    @Mock private lateinit var renderListInteractor: RenderNotificationListInteractor
     @Mock private lateinit var stackController: NotifStackController
     @Mock private lateinit var section: NotifSection
 
+    val featureFlags =
+        FakeFeatureFlagsClassic().apply { setDefault(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR) }
+
     @Before
     fun setUp() {
         initMocks(this)
-        coordinator = StackCoordinator(groupExpansionManagerImpl, notificationIconAreaController)
+        coordinator =
+            StackCoordinator(
+                featureFlags,
+                groupExpansionManagerImpl,
+                notificationIconAreaController,
+                renderListInteractor,
+            )
         coordinator.attach(pipeline)
         afterRenderListListener = withArgCaptor {
             verify(pipeline).addOnAfterRenderListListener(capture())
@@ -68,11 +81,19 @@
 
     @Test
     fun testUpdateNotificationIcons() {
+        featureFlags.set(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR, false)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
         verify(notificationIconAreaController).updateNotificationIcons(eq(listOf(entry)))
     }
 
     @Test
+    fun testSetRenderedListOnInteractor() {
+        featureFlags.set(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR, true)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
+    }
+
+    @Test
     fun testSetNotificationStats_clearableAlerting() {
         whenever(section.bucket).thenReturn(BUCKET_ALERTING)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt
new file mode 100644
index 0000000..683d0aa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.domain.interactor
+
+import android.app.StatusBarManager
+import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
+import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import org.junit.Test
+
+@SmallTest
+class NotificationAlertsInteractorTest : SysuiTestCase() {
+
+    @Component(modules = [SysUITestModule::class])
+    @SysUISingleton
+    interface TestComponent {
+        val underTest: NotificationAlertsInteractor
+        val disableFlags: FakeDisableFlagsRepository
+
+        @Component.Factory
+        interface Factory {
+            fun create(@BindsInstance test: SysuiTestCase): TestComponent
+        }
+    }
+
+    private val testComponent: TestComponent =
+        DaggerNotificationAlertsInteractorTest_TestComponent.factory().create(test = this)
+
+    @Test
+    fun disableFlags_notifAlertsNotDisabled_notifAlertsEnabledTrue() =
+        with(testComponent) {
+            disableFlags.disableFlags.value =
+                DisableFlagsModel(
+                    StatusBarManager.DISABLE_NONE,
+                    StatusBarManager.DISABLE2_NONE,
+                )
+            assertThat(underTest.areNotificationAlertsEnabled()).isTrue()
+        }
+
+    @Test
+    fun disableFlags_notifAlertsDisabled_notifAlertsEnabledFalse() =
+        with(testComponent) {
+            disableFlags.disableFlags.value =
+                DisableFlagsModel(
+                    StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
+                    StatusBarManager.DISABLE2_NONE,
+                )
+            assertThat(underTest.areNotificationAlertsEnabled()).isFalse()
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractorTest.kt
deleted file mode 100644
index fe49016..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsInteractorTest.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.domain.interactor
-
-import android.app.StatusBarManager
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
-import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
-import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepositoryImpl
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import org.junit.Before
-import org.junit.Test
-import org.mockito.Mockito.verify
-
-@SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
-class NotificationsInteractorTest : SysuiTestCase() {
-
-    private lateinit var underTest: NotificationsInteractor
-
-    private val testScope = TestScope(UnconfinedTestDispatcher())
-    private val commandQueue: CommandQueue = mock()
-    private val logBuffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10)
-    private val disableFlagsLogger = DisableFlagsLogger()
-    private lateinit var disableFlagsRepository: DisableFlagsRepository
-
-    @Before
-    fun setUp() {
-        disableFlagsRepository =
-            DisableFlagsRepositoryImpl(
-                commandQueue,
-                DISPLAY_ID,
-                testScope.backgroundScope,
-                mock(),
-                logBuffer,
-                disableFlagsLogger,
-            )
-        underTest = NotificationsInteractor(disableFlagsRepository)
-    }
-
-    @Test
-    fun disableFlags_notifAlertsNotDisabled_notifAlertsEnabledTrue() {
-        val callback = getCommandQueueCallback()
-
-        callback.disable(
-            DISPLAY_ID,
-            StatusBarManager.DISABLE_NONE,
-            StatusBarManager.DISABLE2_NONE,
-            /* animate= */ false
-        )
-
-        assertThat(underTest.areNotificationAlertsEnabled()).isTrue()
-    }
-
-    @Test
-    fun disableFlags_notifAlertsDisabled_notifAlertsEnabledFalse() {
-        val callback = getCommandQueueCallback()
-
-        callback.disable(
-            DISPLAY_ID,
-            StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
-            StatusBarManager.DISABLE2_NONE,
-            /* animate= */ false
-        )
-
-        assertThat(underTest.areNotificationAlertsEnabled()).isFalse()
-    }
-
-    private fun getCommandQueueCallback(): CommandQueue.Callbacks {
-        val callbackCaptor = argumentCaptor<CommandQueue.Callbacks>()
-        verify(commandQueue).addCallback(callbackCaptor.capture())
-        return callbackCaptor.value
-    }
-
-    private companion object {
-        const val DISPLAY_ID = 1
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
new file mode 100644
index 0000000..ca8ea4e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.shared.byKey
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+@SmallTest
+class RenderNotificationsListInteractorTest : SysuiTestCase() {
+
+    private val notifsRepository = ActiveNotificationListRepository()
+    private val notifsInteractor = ActiveNotificationsInteractor(notifsRepository)
+    private val underTest =
+        RenderNotificationListInteractor(
+            notifsRepository,
+            sectionStyleProvider = mock(),
+        )
+
+    @Test
+    fun setRenderedList_preservesOrdering() = runTest {
+        val notifs by collectLastValue(notifsInteractor.notifications)
+        val keys = (1..50).shuffled().map { "$it" }
+        val entries = keys.map { mock<ListEntry> { whenever(key).thenReturn(it) } }
+        underTest.setRenderedList(entries)
+        assertThat(notifs).comparingElementsUsing(byKey).containsExactlyElementsIn(keys).inOrder()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt
new file mode 100644
index 0000000..2a3c1a5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.domain.interactor
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class SeenNotificationsInteractorTest : SysuiTestCase() {
+
+    private val repository = ActiveNotificationListRepository()
+    private val underTest = SeenNotificationsInteractor(repository)
+
+    @Test
+    fun testNoFilteredOutSeenNotifications() = runTest {
+        val hasFilteredOutSeenNotifications by
+            collectLastValue(underTest.hasFilteredOutSeenNotifications)
+
+        underTest.setHasFilteredOutSeenNotifications(false)
+
+        assertThat(hasFilteredOutSeenNotifications).isFalse()
+    }
+
+    @Test
+    fun testHasFilteredOutSeenNotifications() = runTest {
+        val hasFilteredOutSeenNotifications by
+            collectLastValue(underTest.hasFilteredOutSeenNotifications)
+
+        underTest.setHasFilteredOutSeenNotifications(true)
+
+        assertThat(hasFilteredOutSeenNotifications).isTrue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
index f72142f..cc87d7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
@@ -22,8 +22,15 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
+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.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
+import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,6 +38,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.res.R;
 
@@ -44,9 +52,13 @@
 
     FooterView mView;
 
+    Context mSpyContext = spy(mContext);
+
     @Before
     public void setUp() {
-        mView = (FooterView) LayoutInflater.from(mContext).inflate(
+        mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR);
+
+        mView = (FooterView) LayoutInflater.from(mSpyContext).inflate(
                 R.layout.status_bar_notification_footer, null, false);
         mView.setDuration(0);
     }
@@ -102,6 +114,37 @@
     }
 
     @Test
+    public void testSetMessageString_resourceOnlyFetchedOnce() {
+        mView.setMessageString(R.string.unlock_to_see_notif_text);
+        verify(mSpyContext).getString(eq(R.string.unlock_to_see_notif_text));
+
+        clearInvocations(mSpyContext);
+
+        assertThat(((TextView) mView.findViewById(R.id.unlock_prompt_footer))
+                .getText().toString()).contains("Unlock");
+
+        // Set it a few more times, it shouldn't lead to the resource being fetched again
+        mView.setMessageString(R.string.unlock_to_see_notif_text);
+        mView.setMessageString(R.string.unlock_to_see_notif_text);
+
+        verify(mSpyContext, never()).getString(anyInt());
+    }
+
+    @Test
+    public void testSetMessageIcon_resourceOnlyFetchedOnce() {
+        mView.setMessageIcon(R.drawable.ic_friction_lock_closed);
+        verify(mSpyContext).getDrawable(eq(R.drawable.ic_friction_lock_closed));
+
+        clearInvocations(mSpyContext);
+
+        // Set it a few more times, it shouldn't lead to the resource being fetched again
+        mView.setMessageIcon(R.drawable.ic_friction_lock_closed);
+        mView.setMessageIcon(R.drawable.ic_friction_lock_closed);
+
+        verify(mSpyContext, never()).getDrawable(anyInt());
+    }
+
+    @Test
     public void testSetFooterLabelVisible() {
         mView.setFooterLabelVisible(true);
         assertThat(mView.findViewById(R.id.manage_text).getVisibility()).isEqualTo(View.GONE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
new file mode 100644
index 0000000..57a7c3c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.footer.ui.viewmodel
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class FooterViewModelTest : SysuiTestCase() {
+    private val repository = ActiveNotificationListRepository()
+    private val interactor = SeenNotificationsInteractor(repository)
+    private val underTest = FooterViewModel(interactor)
+
+    @Test
+    fun testMessageVisible_whenFilteredNotifications() = runTest {
+        val message by collectLastValue(underTest.message)
+
+        repository.hasFilteredOutSeenNotifications.value = true
+
+        assertThat(message?.visible).isTrue()
+    }
+
+    @Test
+    fun testMessageVisible_whenNoFilteredNotifications() = runTest {
+        val message by collectLastValue(underTest.message)
+
+        repository.hasFilteredOutSeenNotifications.value = false
+
+        assertThat(message?.visible).isFalse()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
new file mode 100644
index 0000000..9988fc7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.icon.domain.interactor
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.TestMocksModule
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.FakeNotificationsKeyguardViewStateRepository
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.byIsAmbient
+import com.android.systemui.statusbar.notification.shared.byIsLastMessageFromReply
+import com.android.systemui.statusbar.notification.shared.byIsPulsing
+import com.android.systemui.statusbar.notification.shared.byIsRowDismissed
+import com.android.systemui.statusbar.notification.shared.byIsSilent
+import com.android.systemui.statusbar.notification.shared.byIsSuppressedFromStatusBar
+import com.android.systemui.statusbar.notification.shared.byKey
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.wm.shell.bubbles.Bubbles
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import java.util.Optional
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class NotificationIconsInteractorTest : SysuiTestCase() {
+
+    private val bubbles: Bubbles = mock()
+
+    @Component(modules = [SysUITestModule::class])
+    @SysUISingleton
+    interface TestComponent {
+        val underTest: NotificationIconsInteractor
+
+        val activeNotificationListRepository: ActiveNotificationListRepository
+        val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository
+        val testScope: TestScope
+
+        @Component.Factory
+        interface Factory {
+            fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+        }
+    }
+
+    val testComponent: TestComponent =
+        DaggerNotificationIconsInteractorTest_TestComponent.factory()
+            .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
+
+    @Before
+    fun setup() =
+        with(testComponent) {
+            activeNotificationListRepository.activeNotifications.value =
+                testIcons.associateBy { it.key }
+        }
+
+    @Test
+    fun filteredEntrySet() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.filteredNotifSet())
+                assertThat(filteredSet).containsExactlyElementsIn(testIcons)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noExpandedBubbles() =
+        with(testComponent) {
+            testScope.runTest {
+                whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+                val filteredSet by collectLastValue(underTest.filteredNotifSet())
+                assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noAmbient() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.filteredNotifSet(showAmbient = false))
+                assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsSuppressedFromStatusBar)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noLowPriority() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by
+                    collectLastValue(underTest.filteredNotifSet(showLowPriority = false))
+                assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noDismissed() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by
+                    collectLastValue(underTest.filteredNotifSet(showDismissed = false))
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsRowDismissed)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noRepliedMessages() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by
+                    collectLastValue(underTest.filteredNotifSet(showRepliedMessages = false))
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsLastMessageFromReply)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noPulsing_notifsNotFullyHidden() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false))
+                keyguardViewStateRepository.setNotificationsFullyHidden(false)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noPulsing_notifsFullyHidden() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false))
+                keyguardViewStateRepository.setNotificationsFullyHidden(true)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
+            }
+        }
+}
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class AlwaysOnDisplayNotificationIconsInteractorTest : SysuiTestCase() {
+
+    private val bubbles: Bubbles = mock()
+
+    @Component(modules = [SysUITestModule::class])
+    @SysUISingleton
+    interface TestComponent {
+        val underTest: AlwaysOnDisplayNotificationIconsInteractor
+
+        val activeNotificationListRepository: ActiveNotificationListRepository
+        val deviceEntryRepository: FakeDeviceEntryRepository
+        val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository
+        val testScope: TestScope
+
+        @Component.Factory
+        interface Factory {
+            fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+        }
+    }
+
+    val testComponent: TestComponent =
+        DaggerAlwaysOnDisplayNotificationIconsInteractorTest_TestComponent.factory()
+            .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
+
+    @Before
+    fun setup() =
+        with(testComponent) {
+            activeNotificationListRepository.activeNotifications.value =
+                testIcons.associateBy { it.key }
+        }
+
+    @Test
+    fun filteredEntrySet_noExpandedBubbles() =
+        with(testComponent) {
+            testScope.runTest {
+                whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noAmbient() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsSuppressedFromStatusBar)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noDismissed() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsRowDismissed)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noRepliedMessages() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsLastMessageFromReply)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_showPulsing_notifsNotFullyHidden_bypassDisabled() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                deviceEntryRepository.setBypassEnabled(false)
+                keyguardViewStateRepository.setNotificationsFullyHidden(false)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassDisabled() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                deviceEntryRepository.setBypassEnabled(false)
+                keyguardViewStateRepository.setNotificationsFullyHidden(true)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noPulsing_notifsNotFullyHidden_bypassEnabled() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                deviceEntryRepository.setBypassEnabled(true)
+                keyguardViewStateRepository.setNotificationsFullyHidden(false)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassEnabled() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.aodNotifs)
+                deviceEntryRepository.setBypassEnabled(true)
+                keyguardViewStateRepository.setNotificationsFullyHidden(true)
+                assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
+            }
+        }
+}
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class StatusBarNotificationIconsInteractorTest : SysuiTestCase() {
+
+    private val bubbles: Bubbles = mock()
+
+    @Component(modules = [SysUITestModule::class])
+    @SysUISingleton
+    interface TestComponent {
+        val underTest: StatusBarNotificationIconsInteractor
+
+        val activeNotificationListRepository: ActiveNotificationListRepository
+        val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository
+        val notificationListenerSettingsRepository: NotificationListenerSettingsRepository
+        val testScope: TestScope
+
+        @Component.Factory
+        interface Factory {
+            fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+        }
+    }
+
+    val testComponent: TestComponent =
+        DaggerStatusBarNotificationIconsInteractorTest_TestComponent.factory()
+            .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
+
+    @Before
+    fun setup() =
+        with(testComponent) {
+            activeNotificationListRepository.activeNotifications.value =
+                testIcons.associateBy { it.key }
+        }
+
+    @Test
+    fun filteredEntrySet_noExpandedBubbles() =
+        with(testComponent) {
+            testScope.runTest {
+                whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noAmbient() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsSuppressedFromStatusBar)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noLowPriority_whenDontShowSilentIcons() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                notificationListenerSettingsRepository.showSilentStatusIcons.value = false
+                assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_showLowPriority_whenShowSilentIcons() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                notificationListenerSettingsRepository.showSilentStatusIcons.value = true
+                assertThat(filteredSet).comparingElementsUsing(byIsSilent).contains(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noDismissed() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsRowDismissed)
+                    .doesNotContain(true)
+            }
+        }
+
+    @Test
+    fun filteredEntrySet_noRepliedMessages() =
+        with(testComponent) {
+            testScope.runTest {
+                val filteredSet by collectLastValue(underTest.statusBarNotifs)
+                assertThat(filteredSet)
+                    .comparingElementsUsing(byIsLastMessageFromReply)
+                    .doesNotContain(true)
+            }
+        }
+}
+
+private val testIcons =
+    listOf(
+        ActiveNotificationModel(
+            key = "notif1",
+        ),
+        ActiveNotificationModel(
+            key = "notif2",
+            isAmbient = true,
+        ),
+        ActiveNotificationModel(
+            key = "notif3",
+            isRowDismissed = true,
+        ),
+        ActiveNotificationModel(
+            key = "notif4",
+            isSilent = true,
+        ),
+        ActiveNotificationModel(
+            key = "notif5",
+            isLastMessageFromReply = true,
+        ),
+        ActiveNotificationModel(
+            key = "notif6",
+            isSuppressedFromStatusBar = true,
+        ),
+        ActiveNotificationModel(
+            key = "notif7",
+            isPulsing = true,
+        ),
+    )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt
deleted file mode 100644
index e57986d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImplTest.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.icon.ui.viewbinder
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.SysUITestModule
-import com.android.TestMocksModule
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FakeFeatureFlagsClassicModule
-import com.android.systemui.flags.Flags
-import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.user.domain.UserDomainLayerModule
-import dagger.BindsInstance
-import dagger.Component
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class NotificationIconAreaControllerViewBinderWrapperImplTest : SysuiTestCase() {
-
-    @Mock private lateinit var dozeParams: DozeParameters
-
-    private lateinit var testComponent: TestComponent
-    private val underTest
-        get() = testComponent.underTest
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        allowTestableLooperAsMainThread()
-
-        testComponent =
-            DaggerNotificationIconAreaControllerViewBinderWrapperImplTest_TestComponent.factory()
-                .create(
-                    test = this,
-                    featureFlags =
-                        FakeFeatureFlagsClassicModule {
-                            set(Flags.FACE_AUTH_REFACTOR, value = false)
-                            set(Flags.MIGRATE_KEYGUARD_STATUS_VIEW, value = false)
-                        },
-                    mocks =
-                        TestMocksModule(
-                            dozeParameters = dozeParams,
-                        ),
-                )
-    }
-
-    @Test
-    fun testNotificationIcons_settingHideIcons() {
-        underTest.settingsListener.onStatusBarIconsBehaviorChanged(true)
-        assertFalse(underTest.shouldShowLowPriorityIcons())
-    }
-
-    @Test
-    fun testNotificationIcons_settingShowIcons() {
-        underTest.settingsListener.onStatusBarIconsBehaviorChanged(false)
-        assertTrue(underTest.shouldShowLowPriorityIcons())
-    }
-
-    @SysUISingleton
-    @Component(
-        modules =
-            [
-                SysUITestModule::class,
-                BiometricsDomainLayerModule::class,
-                UserDomainLayerModule::class,
-            ]
-    )
-    interface TestComponent {
-
-        val underTest: NotificationIconAreaControllerViewBinderWrapperImpl
-
-        @Component.Factory
-        interface Factory {
-            fun create(
-                @BindsInstance test: SysuiTestCase,
-                mocks: TestMocksModule,
-                featureFlags: FakeFeatureFlagsClassicModule,
-            ): TestComponent
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
index e1e7f92..e21ebeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
+import android.graphics.Rect
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.SysUITestModule
@@ -34,10 +35,13 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.power.data.repository.FakePowerRepository
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
+import com.android.systemui.statusbar.phone.data.repository.FakeDarkIconRepository
 import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
 import com.android.systemui.user.domain.UserDomainLayerModule
 import com.android.systemui.util.mockito.whenever
@@ -61,18 +65,6 @@
     @Mock lateinit var dozeParams: DozeParameters
 
     private lateinit var testComponent: TestComponent
-    private val underTest: NotificationIconContainerStatusBarViewModel
-        get() = testComponent.underTest
-    private val deviceProvisioningRepository
-        get() = testComponent.deviceProvisioningRepository
-    private val keyguardTransitionRepository
-        get() = testComponent.keyguardTransitionRepository
-    private val keyguardRepository
-        get() = testComponent.keyguardRepository
-    private val powerRepository
-        get() = testComponent.powerRepository
-    private val scope
-        get() = testComponent.scope
 
     @Before
     fun setup() {
@@ -82,7 +74,6 @@
             DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory()
                 .create(
                     test = this,
-                    // Configurable bindings
                     featureFlags =
                         FakeFeatureFlagsClassicModule {
                             set(Flags.FACE_AUTH_REFACTOR, value = false)
@@ -93,155 +84,247 @@
                             dozeParameters = dozeParams,
                         ),
                 )
-
-        keyguardRepository.setKeyguardShowing(false)
-        deviceProvisioningRepository.setFactoryResetProtectionActive(false)
-        powerRepository.updateWakefulness(
-            rawState = WakefulnessState.AWAKE,
-            lastWakeReason = WakeSleepReason.OTHER,
-            lastSleepReason = WakeSleepReason.OTHER,
-        )
+                .apply {
+                    keyguardRepository.setKeyguardShowing(false)
+                    deviceProvisioningRepository.setFactoryResetProtectionActive(false)
+                    powerRepository.updateWakefulness(
+                        rawState = WakefulnessState.AWAKE,
+                        lastWakeReason = WakeSleepReason.OTHER,
+                        lastSleepReason = WakeSleepReason.OTHER,
+                    )
+                }
     }
 
     @Test
     fun animationsEnabled_isFalse_whenFrpIsActive() =
-        scope.runTest {
-            deviceProvisioningRepository.setFactoryResetProtectionActive(true)
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                deviceProvisioningRepository.setFactoryResetProtectionActive(true)
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        transitionState = TransitionState.STARTED,
+                    )
                 )
-            )
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isFalse()
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isFalse()
+            }
         }
 
     @Test
     fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() =
-        scope.runTest {
-            powerRepository.updateWakefulness(
-                rawState = WakefulnessState.ASLEEP,
-                lastWakeReason = WakeSleepReason.POWER_BUTTON,
-                lastSleepReason = WakeSleepReason.OTHER,
-            )
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.ASLEEP,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
                 )
-            )
-            keyguardRepository.setDozeTransitionModel(
-                DozeTransitionModel(
-                    to = DozeStateModel.DOZE_AOD,
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        transitionState = TransitionState.STARTED,
+                    )
                 )
-            )
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isFalse()
+                keyguardRepository.setDozeTransitionModel(
+                    DozeTransitionModel(
+                        to = DozeStateModel.DOZE_AOD,
+                    )
+                )
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isFalse()
+            }
         }
 
     @Test
     fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() =
-        scope.runTest {
-            powerRepository.updateWakefulness(
-                rawState = WakefulnessState.ASLEEP,
-                lastWakeReason = WakeSleepReason.POWER_BUTTON,
-                lastSleepReason = WakeSleepReason.OTHER,
-            )
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.ASLEEP,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
                 )
-            )
-            keyguardRepository.setDozeTransitionModel(
-                DozeTransitionModel(
-                    to = DozeStateModel.DOZE_PULSING,
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        transitionState = TransitionState.STARTED,
+                    )
                 )
-            )
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isTrue()
+                keyguardRepository.setDozeTransitionModel(
+                    DozeTransitionModel(
+                        to = DozeStateModel.DOZE_PULSING,
+                    )
+                )
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isTrue()
+            }
         }
 
     @Test
     fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() =
-        scope.runTest {
-            powerRepository.updateWakefulness(
-                rawState = WakefulnessState.STARTING_TO_SLEEP,
-                lastWakeReason = WakeSleepReason.POWER_BUTTON,
-                lastSleepReason = WakeSleepReason.OTHER,
-            )
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.GONE,
-                    to = KeyguardState.AOD,
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.STARTING_TO_SLEEP,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
                 )
-            )
-            whenever(dozeParams.shouldControlScreenOff()).thenReturn(false)
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isFalse()
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        from = KeyguardState.GONE,
+                        to = KeyguardState.AOD,
+                        transitionState = TransitionState.STARTED,
+                    )
+                )
+                whenever(dozeParams.shouldControlScreenOff()).thenReturn(false)
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isFalse()
+            }
         }
 
     @Test
     fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
-        scope.runTest {
-            powerRepository.updateWakefulness(
-                rawState = WakefulnessState.STARTING_TO_SLEEP,
-                lastWakeReason = WakeSleepReason.POWER_BUTTON,
-                lastSleepReason = WakeSleepReason.OTHER,
-            )
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.GONE,
-                    to = KeyguardState.AOD,
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.STARTING_TO_SLEEP,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
                 )
-            )
-            whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isTrue()
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        from = KeyguardState.GONE,
+                        to = KeyguardState.AOD,
+                        transitionState = TransitionState.STARTED,
+                    )
+                )
+                whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isTrue()
+            }
         }
 
     @Test
     fun animationsEnabled_isTrue_whenNotAsleep() =
-        scope.runTest {
-            powerRepository.updateWakefulness(
-                rawState = WakefulnessState.AWAKE,
-                lastWakeReason = WakeSleepReason.POWER_BUTTON,
-                lastSleepReason = WakeSleepReason.OTHER,
-            )
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    transitionState = TransitionState.STARTED,
+        with(testComponent) {
+            scope.runTest {
+                powerRepository.updateWakefulness(
+                    rawState = WakefulnessState.AWAKE,
+                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                    lastSleepReason = WakeSleepReason.OTHER,
                 )
-            )
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
-            runCurrent()
-            assertThat(animationsEnabled).isTrue()
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        transitionState = TransitionState.STARTED,
+                    )
+                )
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+                runCurrent()
+                assertThat(animationsEnabled).isTrue()
+            }
         }
 
     @Test
     fun animationsEnabled_isTrue_whenKeyguardIsNotShowing() =
-        scope.runTest {
-            val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+        with(testComponent) {
+            scope.runTest {
+                val animationsEnabled by collectLastValue(underTest.animationsEnabled)
 
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    transitionState = TransitionState.STARTED,
+                keyguardTransitionRepository.sendTransitionStep(
+                    TransitionStep(
+                        transitionState = TransitionState.STARTED,
+                    )
                 )
-            )
-            keyguardRepository.setKeyguardShowing(true)
-            runCurrent()
+                keyguardRepository.setKeyguardShowing(true)
+                runCurrent()
 
-            assertThat(animationsEnabled).isFalse()
+                assertThat(animationsEnabled).isFalse()
 
-            keyguardRepository.setKeyguardShowing(false)
-            runCurrent()
+                keyguardRepository.setKeyguardShowing(false)
+                runCurrent()
 
-            assertThat(animationsEnabled).isTrue()
+                assertThat(animationsEnabled).isTrue()
+            }
+        }
+
+    @Test
+    fun iconColors_testsDarkBounds() =
+        with(testComponent) {
+            scope.runTest {
+                darkIconRepository.darkState.value =
+                    SysuiDarkIconDispatcher.DarkChange(
+                        emptyList(),
+                        0f,
+                        0xAABBCC,
+                    )
+                val iconColorsLookup by collectLastValue(underTest.iconColors)
+                assertThat(iconColorsLookup).isNotNull()
+
+                val iconColors = iconColorsLookup?.iconColors(Rect())
+                assertThat(iconColors).isNotNull()
+                iconColors!!
+
+                assertThat(iconColors.tint).isEqualTo(0xAABBCC)
+
+                val staticDrawableColor = iconColors.staticDrawableColor(Rect(), isColorized = true)
+
+                assertThat(staticDrawableColor).isEqualTo(0xAABBCC)
+            }
+        }
+
+    @Test
+    fun iconColors_staticDrawableColor_nonColorized() =
+        with(testComponent) {
+            scope.runTest {
+                darkIconRepository.darkState.value =
+                    SysuiDarkIconDispatcher.DarkChange(
+                        emptyList(),
+                        0f,
+                        0xAABBCC,
+                    )
+                val iconColorsLookup by collectLastValue(underTest.iconColors)
+                val iconColors = iconColorsLookup?.iconColors(Rect())
+                val staticDrawableColor =
+                    iconColors?.staticDrawableColor(Rect(), isColorized = false)
+                assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
+            }
+        }
+
+    @Test
+    fun iconColors_staticDrawableColor_isColorized_notInDarkTintArea() =
+        with(testComponent) {
+            scope.runTest {
+                darkIconRepository.darkState.value =
+                    SysuiDarkIconDispatcher.DarkChange(
+                        listOf(Rect(0, 0, 5, 5)),
+                        0f,
+                        0xAABBCC,
+                    )
+                val iconColorsLookup by collectLastValue(underTest.iconColors)
+                val iconColors = iconColorsLookup?.iconColors(Rect(1, 1, 4, 4))
+                val staticDrawableColor =
+                    iconColors?.staticDrawableColor(Rect(6, 6, 7, 7), isColorized = true)
+                assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
+            }
+        }
+
+    @Test
+    fun iconColors_notInDarkTintArea() =
+        with(testComponent) {
+            scope.runTest {
+                darkIconRepository.darkState.value =
+                    SysuiDarkIconDispatcher.DarkChange(
+                        listOf(Rect(0, 0, 5, 5)),
+                        0f,
+                        0xAABBCC,
+                    )
+                val iconColorsLookup by collectLastValue(underTest.iconColors)
+                val iconColors = iconColorsLookup?.iconColors(Rect(6, 6, 7, 7))
+                assertThat(iconColors).isNull()
+            }
         }
 
     @SysUISingleton
@@ -249,7 +332,6 @@
         modules =
             [
                 SysUITestModule::class,
-                // Real impls
                 BiometricsDomainLayerModule::class,
                 UserDomainLayerModule::class,
             ]
@@ -258,6 +340,7 @@
 
         val underTest: NotificationIconContainerStatusBarViewModel
 
+        val darkIconRepository: FakeDarkIconRepository
         val deviceProvisioningRepository: FakeDeviceProvisioningRepository
         val keyguardTransitionRepository: FakeKeyguardTransitionRepository
         val keyguardRepository: FakeKeyguardRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalkerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalkerTest.kt
index a0f5048..4bb28ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalkerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalkerTest.kt
@@ -50,8 +50,8 @@
 
     @Test
     fun testViewWalker_plainNotification_withPublicView() {
-        val icon = Icon.createWithBitmap(Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888))
-        val publicIcon = Icon.createWithBitmap(Bitmap.createBitmap(40, 40, Bitmap.Config.ARGB_8888))
+        val icon = Icon.createWithBitmap(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
+        val publicIcon = Icon.createWithBitmap(Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888))
         testHelper.setDefaultInflationFlags(NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL)
         val row =
             testHelper.createRow(
@@ -122,9 +122,9 @@
 
     @Test
     fun testViewWalker_bigPictureNotification() {
-        val bigPicture = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)
-        val icon = Icon.createWithBitmap(Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888))
-        val largeIcon = Icon.createWithBitmap(Bitmap.createBitmap(60, 60, Bitmap.Config.ARGB_8888))
+        val bigPicture = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)
+        val icon = Icon.createWithBitmap(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
+        val largeIcon = Icon.createWithBitmap(Bitmap.createBitmap(30, 30, Bitmap.Config.ARGB_8888))
         val row =
             testHelper.createRow(
                 Notification.Builder(mContext)
@@ -182,8 +182,8 @@
 
     @Test
     fun testViewWalker_customView() {
-        val icon = Icon.createWithBitmap(Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888))
-        val bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)
+        val icon = Icon.createWithBitmap(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
+        val bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888)
 
         val views = RemoteViews(mContext.packageName, R.layout.custom_view_dark)
         views.setImageViewBitmap(R.id.custom_view_dark_image, bitmap)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt
index 23ae26c..1bb7b61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt
@@ -24,9 +24,9 @@
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.internal.widget.NotificationDrawableConsumer
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.graphics.ImageLoader
+import com.android.systemui.res.R
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -45,6 +45,7 @@
 import org.mockito.Mockito.verifyZeroInteractions
 
 private const val FREE_IMAGE_DELAY_MS = 4000L
+private const val MAX_IMAGE_SIZE = 512 // size of the test drawables in pixels
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
@@ -81,6 +82,7 @@
     @Before
     fun setUp() {
         allowTestableLooperAsMainThread()
+        overrideMaxImageSizes()
         iconManager =
             BigPictureIconManager(
                 context,
@@ -430,6 +432,17 @@
             verifyZeroInteractions(mockConsumer)
         }
 
+    private fun overrideMaxImageSizes() {
+        testableResources.addOverride(
+            com.android.internal.R.dimen.notification_big_picture_max_width,
+            MAX_IMAGE_SIZE
+        )
+        testableResources.addOverride(
+            com.android.internal.R.dimen.notification_big_picture_max_height,
+            MAX_IMAGE_SIZE
+        )
+    }
+
     private fun assertIsPlaceHolder(drawable: Drawable) {
         assertThat(drawable).isInstanceOf(PlaceHolderDrawable::class.java)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt
new file mode 100644
index 0000000..0eac1ae
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shared/TestActiveNotificationModel.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.shared
+
+import com.google.common.truth.Correspondence
+
+val byKey: Correspondence<ActiveNotificationModel, String> =
+    Correspondence.transforming({ it?.key }, "has a key of")
+val byIsAmbient: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming({ it?.isAmbient }, "has an isAmbient value of")
+val byIsSuppressedFromStatusBar: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming(
+        { it?.isSuppressedFromStatusBar },
+        "has an isSuppressedFromStatusBar value of",
+    )
+val byIsSilent: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming({ it?.isSilent }, "has an isSilent value of")
+val byIsRowDismissed: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming({ it?.isRowDismissed }, "has an isRowDismissed value of")
+val byIsLastMessageFromReply: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming(
+        { it?.isLastMessageFromReply },
+        "has an isLastMessageFromReply value of"
+    )
+val byIsPulsing: Correspondence<ActiveNotificationModel, Boolean> =
+    Correspondence.transforming({ it?.isPulsing }, "has an isPulsing value of")
+
+@Suppress("TestFunctionName")
+fun ActiveNotificationModel(
+    key: String,
+    isAmbient: Boolean = false,
+    isRowDismissed: Boolean = false,
+    isSilent: Boolean = false,
+    isLastMessageFromReply: Boolean = false,
+    isSuppressedFromStatusBar: Boolean = false,
+    isPulsing: Boolean = false,
+) =
+    ActiveNotificationModel(
+        key = key,
+        groupKey = null,
+        isAmbient = isAmbient,
+        isRowDismissed = isRowDismissed,
+        isSilent = isSilent,
+        isLastMessageFromReply = isLastMessageFromReply,
+        isSuppressedFromStatusBar = isSuppressedFromStatusBar,
+        isPulsing = isPulsing,
+        aodIcon = null,
+        shelfIcon = null,
+        statusBarIcon = null,
+    )
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 20197e3..3dafb23 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
@@ -82,13 +82,13 @@
 import com.android.systemui.statusbar.notification.collection.render.NotifStats;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository;
+import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
 import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
-import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor;
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -171,8 +171,8 @@
     @Captor
     private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
 
-    private final NotificationListInteractor mNotificationListInteractor =
-            new NotificationListInteractor(new NotificationListRepository());
+    private final SeenNotificationsInteractor mSeenNotificationsInteractor =
+            new SeenNotificationsInteractor(new ActiveNotificationListRepository());
 
     private NotificationStackScrollLayoutController mController;
 
@@ -504,7 +504,7 @@
     @Test
     public void testSetNotifStats_updatesHasFilteredOutSeenNotifications() {
         initController(/* viewIsAttached= */ true);
-        mNotificationListInteractor.setHasFilteredOutSeenNotifications(true);
+        mSeenNotificationsInteractor.setHasFilteredOutSeenNotifications(true);
         mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
         verify(mNotificationStackScrollLayout).setHasFilteredOutSeenNotifications(true);
         verify(mNotificationStackScrollLayout).updateFooter();
@@ -704,7 +704,7 @@
                 mUiEventLogger,
                 mRemoteInputManager,
                 mVisibilityLocationProviderDelegator,
-                mNotificationListInteractor,
+                mSeenNotificationsInteractor,
                 mShadeController,
                 mJankMonitor,
                 mStackLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 033c96a..8f36d4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -19,6 +19,8 @@
 import static android.view.View.GONE;
 import static android.view.WindowInsets.Type.ime;
 
+import static com.android.systemui.Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR;
+import static com.android.systemui.flags.SetFlagsRuleExtensionsKt.setFlagDefault;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.RUBBER_BAND_FACTOR_NORMAL;
@@ -165,6 +167,11 @@
         mFeatureFlags.setDefault(Flags.NOTIFICATION_SHELF_REFACTOR);
         mFeatureFlags.setDefault(Flags.NEW_AOD_TRANSITION);
         mFeatureFlags.setDefault(Flags.UNCLEARED_TRANSIENT_HUN_FIX);
+        // Some tests in this file test the FooterView. Since we're refactoring the FooterView
+        // business logic out of the NSSL, the behavior tested in this file will eventually be
+        // tested directly in the new FooterView stack. For now, we just want to make sure that the
+        // old behavior is preserved when the flag is off.
+        setFlagDefault(mSetFlagsRule, FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR);
 
         // Inject dependencies before initializing the layout
         mDependency.injectTestDependency(FeatureFlags.class, mFeatureFlags);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 49906dc..08ef477 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -62,6 +62,10 @@
         )
 
     private val testableResources = mContext.getOrCreateTestableResources()
+    private val maxPanelHeight =
+        mContext.resources.displayMetrics.heightPixels -
+                px(R.dimen.notification_panel_margin_top) -
+                px(R.dimen.notification_panel_margin_bottom)
 
     private fun px(@DimenRes id: Int): Float =
             testableResources.resources.getDimensionPixelSize(id).toFloat()
@@ -147,7 +151,7 @@
         stackScrollAlgorithm.initView(context)
         hostView.removeAllViews()
         hostView.addView(emptyShadeView)
-        ambientState.layoutMaxHeight = 1280
+        ambientState.layoutMaxHeight = maxPanelHeight.toInt()
 
         stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
 
@@ -155,7 +159,7 @@
                 context.resources.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom)
         val fullHeight = ambientState.layoutMaxHeight + marginBottom - ambientState.stackY
         val centeredY = ambientState.stackY + fullHeight / 2f - emptyShadeView.height / 2f
-        assertThat(emptyShadeView.viewState?.yTranslation).isEqualTo(centeredY)
+        assertThat(emptyShadeView.viewState.yTranslation).isEqualTo(centeredY)
     }
 
     @Test
@@ -356,7 +360,7 @@
         whenever(notificationRow.canViewBeCleared()).thenReturn(false)
         ambientState.isClearAllInProgress = true
         ambientState.isShadeExpanded = true
-        ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+        ambientState.stackEndHeight = maxPanelHeight // plenty space for the footer in the stack
         hostView.addView(footerView)
 
         stackScrollAlgorithm.resetViewStates(ambientState, 0)
@@ -370,7 +374,7 @@
         whenever(notificationRow.canViewBeCleared()).thenReturn(true)
         ambientState.isClearAllInProgress = true
         ambientState.isShadeExpanded = true
-        ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+        ambientState.stackEndHeight = maxPanelHeight // plenty space for the footer in the stack
         hostView.addView(footerView)
 
         stackScrollAlgorithm.resetViewStates(ambientState, 0)
@@ -382,7 +386,7 @@
     fun resetViewStates_clearAllInProgress_allRowsRemoved_emptyShade_footerHidden() {
         ambientState.isClearAllInProgress = true
         ambientState.isShadeExpanded = true
-        ambientState.stackEndHeight = 1000f // plenty space for the footer in the stack
+        ambientState.stackEndHeight = maxPanelHeight // plenty space for the footer in the stack
         hostView.removeAllViews() // remove all rows
         hostView.addView(footerView)
 
@@ -1006,7 +1010,7 @@
     }
 
     private fun resetViewStates_stackMargin_changesHunYTranslation() {
-        val stackTopMargin = 50
+        val stackTopMargin = bigGap.toInt() // a gap smaller than the headsUpInset
         val headsUpTranslationY = stackScrollAlgorithm.mHeadsUpInset - stackTopMargin
 
         // we need the shelf to mock the real-life behaviour of StackScrollAlgorithm#updateChild
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index 593c587..472709c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -42,6 +42,8 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
 import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -96,18 +98,21 @@
     @Mock private BiometricUnlockController mBiometricUnlockController;
     @Mock private AuthController mAuthController;
     @Mock private DozeHost.Callback mCallback;
-
     @Mock private DozeInteractor mDozeInteractor;
+
+    private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        mFeatureFlags.setDefault(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR);
         mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle,
-                mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager,
-                mBatteryController, mScrimController, () -> mBiometricUnlockController,
-                () -> mAssistManager, mDozeScrimController,
-                mKeyguardUpdateMonitor, mPulseExpansionHandler,
-                mNotificationShadeWindowController, mNotificationWakeUpCoordinator,
-                mAuthController, mNotificationIconAreaController, mDozeInteractor);
+                mStatusBarStateController, mDeviceProvisionedController, mFeatureFlags,
+                mHeadsUpManager, mBatteryController, mScrimController,
+                () -> mBiometricUnlockController, () -> mAssistManager, mDozeScrimController,
+                mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController,
+                mNotificationWakeUpCoordinator, mAuthController, mNotificationIconAreaController,
+                mDozeInteractor);
 
         mDozeServiceHost.initialize(
                 mCentralSurfaces,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index ee4f208..53c621d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -53,7 +53,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
-import com.android.systemui.statusbar.notification.domain.interactor.NotificationsInteractor;
+import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -79,8 +79,8 @@
     private CommandQueue mCommandQueue;
     private FakeMetricsLogger mMetricsLogger;
     private final ShadeController mShadeController = mock(ShadeController.class);
-    private final NotificationsInteractor mNotificationsInteractor =
-            mock(NotificationsInteractor.class);
+    private final NotificationAlertsInteractor mNotificationAlertsInteractor =
+            mock(NotificationAlertsInteractor.class);
     private final KeyguardStateController mKeyguardStateController =
             mock(KeyguardStateController.class);
     private final InitController mInitController = new InitController();
@@ -116,7 +116,7 @@
                 mock(NotificationShadeWindowController.class),
                 mock(DynamicPrivacyController.class),
                 mKeyguardStateController,
-                mNotificationsInteractor,
+                mNotificationAlertsInteractor,
                 mock(LockscreenShadeTransitionController.class),
                 mock(PowerInteractor.class),
                 mCommandQueue,
@@ -226,7 +226,7 @@
                 .setTag("a")
                 .setNotification(n)
                 .build();
-        when(mNotificationsInteractor.areNotificationAlertsEnabled()).thenReturn(false);
+        when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);
 
         assertTrue("When alerts aren't enabled, interruptions are suppressed",
                 mInterruptSuppressor.suppressInterruptions(entry));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
index 21d22bc..1e628bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
@@ -13,13 +13,17 @@
  */
 package com.android.systemui.statusbar.phone
 
+import android.content.res.Configuration
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.policy.ConfigurationController
 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.mock
+import com.google.common.truth.Truth.assertThat
 import kotlin.test.Test
 import org.junit.Before
 import org.junit.runner.RunWith
@@ -31,6 +35,7 @@
 class SystemUIBottomSheetDialogTest : SysuiTestCase() {
 
     private val configurationController = mock<ConfigurationController>()
+    private val config = mock<Configuration>()
 
     private lateinit var dialog: SystemUIBottomSheetDialog
 
@@ -53,4 +58,23 @@
 
         verify(configurationController).removeCallback(any())
     }
+
+    @Test
+    fun onConfigurationChanged_calledInSubclass() {
+        var onConfigChangedCalled = false
+        val subclass =
+            object : SystemUIBottomSheetDialog(mContext, configurationController) {
+                override fun onConfigurationChanged() {
+                    onConfigChangedCalled = true
+                }
+            }
+
+        subclass.show()
+
+        val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
+        verify(configurationController).addCallback(capture(captor))
+        captor.value.onConfigChanged(config)
+
+        assertThat(onConfigChangedCalled).isTrue()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/LayoutInflaterUtilTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/LayoutInflaterUtilTest.kt
new file mode 100644
index 0000000..1c8465a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/LayoutInflaterUtilTest.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import android.content.Context
+import android.testing.AndroidTestingRunner
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.view.reinflateAndBindLatest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class LayoutInflaterUtilTest : SysuiTestCase() {
+    @JvmField @Rule val mockito = MockitoJUnit.rule()
+
+    private var inflationCount = 0
+    private var callbackCount = 0
+    @Mock private lateinit var disposableHandle: DisposableHandle
+
+    inner class TestLayoutInflater : LayoutInflater(context) {
+        override fun inflate(resource: Int, root: ViewGroup?, attachToRoot: Boolean): View {
+            inflationCount++
+            return View(context)
+        }
+
+        override fun cloneInContext(p0: Context?): LayoutInflater {
+            // not needed for this test
+            return this
+        }
+    }
+
+    val underTest = TestLayoutInflater()
+
+    @After
+    fun cleanUp() {
+        inflationCount = 0
+        callbackCount = 0
+    }
+
+    @Test
+    fun testReinflateAndBindLatest_inflatesWithoutEmission() = runTest {
+        backgroundScope.launch {
+            underTest.reinflateAndBindLatest(
+                resource = 0,
+                root = null,
+                attachToRoot = false,
+                emptyFlow<Unit>()
+            ) {
+                callbackCount++
+                null
+            }
+        }
+
+        // Inflates without an emission
+        runCurrent()
+        assertThat(inflationCount).isEqualTo(1)
+        assertThat(callbackCount).isEqualTo(1)
+    }
+
+    @Test
+    fun testReinflateAndBindLatest_reinflatesOnEmission() = runTest {
+        val observable = MutableSharedFlow<Unit>()
+        val flow = observable.asSharedFlow()
+        backgroundScope.launch {
+            underTest.reinflateAndBindLatest(
+                resource = 0,
+                root = null,
+                attachToRoot = false,
+                flow
+            ) {
+                callbackCount++
+                null
+            }
+        }
+
+        listOf(1, 2, 3).forEach { count ->
+            runCurrent()
+            assertThat(inflationCount).isEqualTo(count)
+            assertThat(callbackCount).isEqualTo(count)
+            observable.emit(Unit)
+        }
+    }
+
+    @Test
+    fun testReinflateAndBindLatest_disposesOnCancel() = runTest {
+        val job = launch {
+            underTest.reinflateAndBindLatest(
+                resource = 0,
+                root = null,
+                attachToRoot = false,
+                emptyFlow()
+            ) {
+                callbackCount++
+                disposableHandle
+            }
+        }
+
+        runCurrent()
+        job.cancelAndJoin()
+        verify(disposableHandle).dispose()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ui/AnimatedValueTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/ui/AnimatedValueTest.kt
index aaf8d07..6e3a732 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/ui/AnimatedValueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ui/AnimatedValueTest.kt
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.util.ui
 
 import android.testing.AndroidTestingRunner
@@ -20,6 +22,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.launchIn
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
index 5dcc742..8353cf7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
@@ -34,7 +34,10 @@
     private val _scaleForResolution = MutableStateFlow(1f)
     override val scaleForResolution: Flow<Float> = _scaleForResolution.asStateFlow()
 
-    suspend fun onAnyConfigurationChange() {
+    private val pixelSizes = mutableMapOf<Int, MutableStateFlow<Int>>()
+    private val colors = mutableMapOf<Int, MutableStateFlow<Int>>()
+
+    fun onAnyConfigurationChange() {
         _onAnyConfigurationChange.tryEmit(Unit)
     }
 
@@ -42,12 +45,12 @@
         _scaleForResolution.value = scale
     }
 
-    override fun getResolutionScale(): Float {
-        return _scaleForResolution.value
-    }
+    override fun getResolutionScale(): Float = _scaleForResolution.value
 
-    override fun getDimensionPixelSize(id: Int): Int {
-        return 0
+    override fun getDimensionPixelSize(id: Int): Int = pixelSizes[id]?.value ?: 0
+
+    fun setDimensionPixelSize(id: Int, pixelSize: Int) {
+        pixelSizes.getOrPut(id) { MutableStateFlow(pixelSize) }.value = pixelSize
     }
 }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
index 5cd09d8..5fd0b4f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
@@ -43,9 +43,10 @@
     mock<DisplayRepository.PendingDisplay> { whenever(this.id).thenReturn(id) }
 
 /** Fake [DisplayRepository] implementation for testing. */
-class FakeDisplayRepository() : DisplayRepository {
-    private val flow = MutableSharedFlow<Set<Display>>()
-    private val pendingDisplayFlow = MutableSharedFlow<DisplayRepository.PendingDisplay?>()
+class FakeDisplayRepository : DisplayRepository {
+    private val flow = MutableSharedFlow<Set<Display>>(replay = 1)
+    private val pendingDisplayFlow =
+        MutableSharedFlow<DisplayRepository.PendingDisplay?>(replay = 1)
 
     /** Emits [value] as [displays] flow value. */
     suspend fun emit(value: Set<Display>) = flow.emit(value)
@@ -59,7 +60,7 @@
     override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?>
         get() = pendingDisplayFlow
 
-    private val _displayChangeEvent = MutableSharedFlow<Int>()
+    private val _displayChangeEvent = MutableSharedFlow<Int>(replay = 1)
     override val displayChangeEvent: Flow<Int> = _displayChangeEvent
     suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId)
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileDataInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileDataInteractor.kt
index 1cb4ab7..5593596 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileDataInteractor.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileDataInteractor.kt
@@ -19,62 +19,35 @@
 import javax.annotation.CheckReturnValue
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.flatMapLatest
 
 class FakeQSTileDataInteractor<T>(
-    private val dataFlow: MutableSharedFlow<FakeData<T>> =
-        MutableSharedFlow(replay = Int.MAX_VALUE),
+    private val dataFlow: MutableSharedFlow<T> = MutableSharedFlow(replay = Int.MAX_VALUE),
     private val availabilityFlow: MutableSharedFlow<Boolean> =
         MutableSharedFlow(replay = Int.MAX_VALUE),
 ) : QSTileDataInteractor<T> {
 
-    private val mutableDataRequests = mutableListOf<QSTileDataRequest>()
-    val dataRequests: List<QSTileDataRequest> = mutableDataRequests
+    private val mutableDataRequests = mutableListOf<DataRequest>()
+    val dataRequests: List<DataRequest> = mutableDataRequests
 
-    private val mutableAvailabilityRequests = mutableListOf<Unit>()
-    val availabilityRequests: List<Unit> = mutableAvailabilityRequests
+    private val mutableAvailabilityRequests = mutableListOf<AvailabilityRequest>()
+    val availabilityRequests: List<AvailabilityRequest> = mutableAvailabilityRequests
 
-    @CheckReturnValue
-    fun emitData(data: T): FilterEmit =
-        object : FilterEmit {
-            override fun forRequest(request: QSTileDataRequest): Boolean =
-                dataFlow.tryEmit(FakeData(data, DataFilter.ForRequest(request)))
-            override fun forAnyRequest(): Boolean = dataFlow.tryEmit(FakeData(data, DataFilter.Any))
-        }
+    @CheckReturnValue fun emitData(data: T): Boolean = dataFlow.tryEmit(data)
 
     fun tryEmitAvailability(isAvailable: Boolean): Boolean = availabilityFlow.tryEmit(isAvailable)
     suspend fun emitAvailability(isAvailable: Boolean) = availabilityFlow.emit(isAvailable)
 
-    override fun tileData(qsTileDataRequest: QSTileDataRequest): Flow<T> {
-        mutableDataRequests.add(qsTileDataRequest)
-        return dataFlow
-            .filter {
-                when (it.filter) {
-                    is DataFilter.Any -> true
-                    is DataFilter.ForRequest -> it.filter.request == qsTileDataRequest
-                }
-            }
-            .map { it.data }
+    override fun tileData(userId: Int, triggers: Flow<DataUpdateTrigger>): Flow<T> {
+        mutableDataRequests.add(DataRequest(userId))
+        return triggers.flatMapLatest { dataFlow }
     }
 
-    override fun availability(): Flow<Boolean> {
-        mutableAvailabilityRequests.add(Unit)
+    override fun availability(userId: Int): Flow<Boolean> {
+        mutableAvailabilityRequests.add(AvailabilityRequest(userId))
         return availabilityFlow
     }
 
-    interface FilterEmit {
-        fun forRequest(request: QSTileDataRequest): Boolean
-        fun forAnyRequest(): Boolean
-    }
-
-    class FakeData<T>(
-        val data: T,
-        val filter: DataFilter,
-    )
-
-    sealed class DataFilter {
-        object Any : DataFilter()
-        class ForRequest(val request: QSTileDataRequest) : DataFilter()
-    }
+    data class DataRequest(val userId: Int)
+    data class AvailabilityRequest(val userId: Int)
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
index 9c99cb5..597d52d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/FakeQSTileUserActionInteractor.kt
@@ -16,22 +16,19 @@
 
 package com.android.systemui.qs.tiles.base.interactor
 
-import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 
 class FakeQSTileUserActionInteractor<T> : QSTileUserActionInteractor<T> {
 
     private val mutex: Mutex = Mutex()
-    private val mutableInputs: MutableList<FakeInput<T>> = mutableListOf()
+    private val mutableInputs: MutableList<QSTileInput<T>> = mutableListOf()
 
-    val inputs: List<FakeInput<T>> = mutableInputs
+    val inputs: List<QSTileInput<T>> = mutableInputs
 
-    fun lastInput(): FakeInput<T>? = inputs.lastOrNull()
+    fun lastInput(): QSTileInput<T>? = inputs.lastOrNull()
 
-    override suspend fun handleInput(userAction: QSTileUserAction, currentData: T) {
-        mutex.withLock { mutableInputs.add(FakeInput(userAction, currentData)) }
+    override suspend fun handleInput(input: QSTileInput<T>) {
+        mutex.withLock { mutableInputs.add(input) }
     }
-
-    data class FakeInput<T>(val userAction: QSTileUserAction, val data: T)
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
index e59f642..8f18e13 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
@@ -15,8 +15,10 @@
  */
 package com.android.systemui.statusbar.data
 
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepositoryModule
 import com.android.systemui.statusbar.disableflags.data.FakeStatusBarDisableFlagsDataLayerModule
 import com.android.systemui.statusbar.notification.data.FakeStatusBarNotificationsDataLayerModule
+import com.android.systemui.statusbar.phone.data.FakeStatusBarPhoneDataLayerModule
 import com.android.systemui.statusbar.pipeline.data.FakeStatusBarPipelineDataLayerModule
 import com.android.systemui.statusbar.policy.data.FakeStatusBarPolicyDataLayerModule
 import dagger.Module
@@ -25,7 +27,9 @@
     includes =
         [
             FakeStatusBarDisableFlagsDataLayerModule::class,
+            FakeStatusBarModeRepositoryModule::class,
             FakeStatusBarNotificationsDataLayerModule::class,
+            FakeStatusBarPhoneDataLayerModule::class,
             FakeStatusBarPipelineDataLayerModule::class,
             FakeStatusBarPolicyDataLayerModule::class,
         ]
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
similarity index 81%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
index 61ba464..f25d282 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
@@ -18,17 +18,17 @@
 
 import com.android.systemui.statusbar.data.model.StatusBarAppearance
 import com.android.systemui.statusbar.data.model.StatusBarMode
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
 import kotlinx.coroutines.flow.MutableStateFlow
 
-class FakeStatusBarModeRepository : StatusBarModeRepository {
+class FakeStatusBarModeRepository @Inject constructor() : StatusBarModeRepository {
     override val isTransientShown = MutableStateFlow(false)
     override val isInFullscreenMode = MutableStateFlow(false)
     override val statusBarAppearance = MutableStateFlow<StatusBarAppearance?>(null)
     override val statusBarMode = MutableStateFlow(StatusBarMode.TRANSPARENT)
 
-    override fun onStatusBarViewInitialized(component: StatusBarFragmentComponent) {}
-
     override fun showTransient() {
         isTransientShown.value = true
     }
@@ -36,3 +36,8 @@
         isTransientShown.value = false
     }
 }
+
+@Module
+interface FakeStatusBarModeRepositoryModule {
+    @Binds fun bindFake(fake: FakeStatusBarModeRepository): StatusBarModeRepository
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/FakeStatusBarPhoneDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/FakeStatusBarPhoneDataLayerModule.kt
new file mode 100644
index 0000000..d2c3b7a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/FakeStatusBarPhoneDataLayerModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.phone.data
+
+import com.android.systemui.statusbar.phone.data.repository.FakeDarkIconRepositoryModule
+import dagger.Module
+
+@Module(includes = [FakeDarkIconRepositoryModule::class]) object FakeStatusBarPhoneDataLayerModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt
new file mode 100644
index 0000000..50d3f0a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/data/repository/FakeDarkIconRepository.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.phone.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+
+@SysUISingleton
+class FakeDarkIconRepository @Inject constructor() : DarkIconRepository {
+    override val darkState = MutableStateFlow(DarkChange(emptyList(), 0f, 0))
+}
+
+@Module
+interface FakeDarkIconRepositoryModule {
+    @Binds fun bindFake(fake: FakeDarkIconRepository): DarkIconRepository
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b696998..4dca5a5 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -136,7 +136,6 @@
         ":display-device-config",
         ":display-layout-config",
         ":device-state-config",
-        ":framework-core-nfc-infcadapter-sources",
         "java/com/android/server/EventLogTags.logtags",
         "java/com/android/server/am/EventLogTags.logtags",
         "java/com/android/server/wm/EventLogTags.logtags",
@@ -149,6 +148,7 @@
         "android.hardware.light-V2.0-java",
         "android.hardware.gnss-V2-java",
         "android.hardware.vibrator-V2-java",
+        "android.nfc.flags-aconfig-java",
         "app-compat-annotations",
         "framework-tethering.stubs.module_lib",
         "service-art.stubs.system_server",
@@ -196,7 +196,6 @@
         "android.hardware.rebootescrow-V1-java",
         "android.hardware.power.stats-V2-java",
         "android.hidl.manager-V1.2-java",
-        "android.nfc.flags-aconfig-java",
         "cbor-java",
         "icu4j_calendar_astronomer",
         "android.security.aaid_aidl-java",
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 8624dd5..3af0e8c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -386,15 +386,14 @@
     private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
 
     /**
-     * mLocalUnlockedUsers affects the return value of isUserUnlocked.  If
-     * any value in the array changes, then the binder cache for
-     * isUserUnlocked must be invalidated.  When adding mutating methods to
-     * WatchedLockedUsers, be sure to invalidate the cache in the new
-     * methods.
+     * mCeUnlockedUsers affects the return value of {@link UserManager#isUserUnlocked}.  If any
+     * value in the array changes, then the binder cache for {@link UserManager#isUserUnlocked} must
+     * be invalidated.  When adding mutating methods to this class, be sure to invalidate the cache
+     * in the new methods.
      */
-    private static class WatchedLockedUsers {
+    private static class WatchedUnlockedUsers {
         private int[] users = EmptyArray.INT;
-        public WatchedLockedUsers() {
+        public WatchedUnlockedUsers() {
             invalidateIsUserUnlockedCache();
         }
         public void append(int userId) {
@@ -426,10 +425,14 @@
         }
     }
 
-    /** Set of users that we know are unlocked. */
+    /** Set of users whose CE storage is unlocked. */
     @GuardedBy("mLock")
-    private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers();
-    /** Set of users that system knows are unlocked. */
+    private WatchedUnlockedUsers mCeUnlockedUsers = new WatchedUnlockedUsers();
+
+    /**
+     * Set of users that are in the RUNNING_UNLOCKED state.  This differs from {@link
+     * mCeUnlockedUsers} in that a user can be stopped but still have its CE storage unlocked.
+     */
     @GuardedBy("mLock")
     private int[] mSystemUnlockedUsers = EmptyArray.INT;
 
@@ -1144,11 +1147,10 @@
         }
     }
 
-    // If vold knows that some users have their storage unlocked already (which
-    // can happen after a "userspace reboot"), then add those users to
-    // mLocalUnlockedUsers.  Do this right away and don't wait until
-    // PHASE_BOOT_COMPLETED, since the system may unlock users before then.
-    private void restoreLocalUnlockedUsers() {
+    // If vold knows that some users have their CE storage unlocked already (which can happen after
+    // a "userspace reboot"), then add those users to mCeUnlockedUsers.  Do this right away and
+    // don't wait until PHASE_BOOT_COMPLETED, since the system may unlock users before then.
+    private void restoreCeUnlockedUsers() {
         final int[] userIds;
         try {
             userIds = mVold.getUnlockedUsers();
@@ -1164,7 +1166,7 @@
                 // reconnecting to vold after it crashed and was restarted, in
                 // which case things will be the other way around --- we'll know
                 // about the unlocked users but vold won't.
-                mLocalUnlockedUsers.appendAll(userIds);
+                mCeUnlockedUsers.appendAll(userIds);
             }
         }
     }
@@ -2075,7 +2077,7 @@
                 connectVold();
             }, DateUtils.SECOND_IN_MILLIS);
         } else {
-            restoreLocalUnlockedUsers();
+            restoreCeUnlockedUsers();
             onDaemonConnected();
         }
     }
@@ -3235,9 +3237,9 @@
 
         try {
             mVold.createUserKey(userId, serialNumber, ephemeral);
-            // New keys are always unlocked.
+            // Since the user's CE key was just created, the user's CE storage is now unlocked.
             synchronized (mLock) {
-                mLocalUnlockedUsers.append(userId);
+                mCeUnlockedUsers.append(userId);
             }
         } catch (Exception e) {
             Slog.wtf(TAG, e);
@@ -3252,9 +3254,9 @@
 
         try {
             mVold.destroyUserKey(userId);
-            // Destroying a key also locks it.
+            // Since the user's CE key was just destroyed, the user's CE storage is now locked.
             synchronized (mLock) {
-                mLocalUnlockedUsers.remove(userId);
+                mCeUnlockedUsers.remove(userId);
             }
         } catch (Exception e) {
             Slog.wtf(TAG, e);
@@ -3281,7 +3283,7 @@
             mVold.unlockUserKey(userId, serialNumber, HexDump.toHexString(secret));
         }
         synchronized (mLock) {
-            mLocalUnlockedUsers.append(userId);
+            mCeUnlockedUsers.append(userId);
         }
     }
 
@@ -3310,14 +3312,14 @@
         }
 
         synchronized (mLock) {
-            mLocalUnlockedUsers.remove(userId);
+            mCeUnlockedUsers.remove(userId);
         }
     }
 
     @Override
     public boolean isUserKeyUnlocked(int userId) {
         synchronized (mLock) {
-            return mLocalUnlockedUsers.contains(userId);
+            return mCeUnlockedUsers.contains(userId);
         }
     }
 
@@ -4716,7 +4718,7 @@
             }
 
             pw.println();
-            pw.println("Local unlocked users: " + mLocalUnlockedUsers);
+            pw.println("CE unlocked users: " + mCeUnlockedUsers);
             pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
         }
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 1650a96..bdda95e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -190,6 +190,7 @@
 
     final MessageHandler mHandler;
 
+    private static final int TIMEOUT_DELAY_MS = 1000 * 60;
     // Messages that can be sent on mHandler
     private static final int MESSAGE_TIMED_OUT = 3;
     private static final int MESSAGE_COPY_SHARED_ACCOUNT = 4;
@@ -4942,6 +4943,7 @@
             synchronized (mSessions) {
                 mSessions.put(toString(), this);
             }
+            scheduleTimeout();
             if (response != null) {
                 try {
                     response.asBinder().linkToDeath(this, 0 /* flags */);
@@ -5109,6 +5111,11 @@
             }
         }
 
+        private void scheduleTimeout() {
+            mHandler.sendMessageDelayed(
+                    mHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS);
+        }
+
         public void cancelTimeout() {
             mHandler.removeMessages(MESSAGE_TIMED_OUT, this);
         }
@@ -5146,6 +5153,9 @@
 
         public void onTimedOut() {
             IAccountManagerResponse response = getResponseAndClose();
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "Session.onTimedOut");
+            }
             if (response != null) {
                 try {
                     response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 31817f1..ef67cbe 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -77,8 +77,10 @@
 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
 import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD;
 import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_BOOT_COMPLETED;
 import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
 import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
 import static android.os.PowerExemptionManager.REASON_PROC_STATE_BTOP;
 import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
 import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
@@ -4840,6 +4842,7 @@
             if (!mConstants.mEnableWaitForFinishAttachApplication) {
                 finishAttachApplicationInner(startSeq, callingUid, pid);
             }
+            maybeSendBootCompletedLocked(app);
         } catch (Exception e) {
             // We need kill the process group here. (b/148588589)
             Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
@@ -5066,6 +5069,45 @@
         }
     }
 
+    /**
+     * Send LOCKED_BOOT_COMPLETED and BOOT_COMPLETED to the package explicitly when unstopped
+     */
+    private void maybeSendBootCompletedLocked(ProcessRecord app) {
+        // Nothing to do if it wasn't previously stopped
+        if (!android.content.pm.Flags.stayStopped() || !app.wasForceStopped()) return;
+
+        // Send LOCKED_BOOT_COMPLETED, if necessary
+        if (app.getApplicationInfo().isEncryptionAware()) {
+            sendBootBroadcastToAppLocked(app, new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED),
+                    REASON_LOCKED_BOOT_COMPLETED);
+        }
+        // Send BOOT_COMPLETED if the user is unlocked
+        if (StorageManager.isUserKeyUnlocked(app.userId)) {
+            sendBootBroadcastToAppLocked(app, new Intent(Intent.ACTION_BOOT_COMPLETED),
+                    REASON_BOOT_COMPLETED);
+        }
+        app.setWasForceStopped(false);
+    }
+
+    /** Send a boot_completed broadcast to app */
+    private void sendBootBroadcastToAppLocked(ProcessRecord app, Intent intent,
+            @PowerExemptionManager.ReasonCode int reason) {
+        intent.setPackage(app.info.packageName);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, app.userId);
+        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+        final BroadcastOptions bOptions = mUserController.getTemporaryAppAllowlistBroadcastOptions(
+                reason);
+
+        broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null,
+                new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+                null, null, AppOpsManager.OP_NONE,
+                bOptions.toBundle(), true,
+                false, MY_PID, SYSTEM_UID,
+                SYSTEM_UID, MY_PID, app.userId);
+    }
+
     @Override
     public void showBootMessage(final CharSequence msg, final boolean always) {
         if (Binder.getCallingUid() != myUid()) {
@@ -5476,7 +5518,7 @@
                             + " Calling package: " + packageName + "; intent: " + intent
                             + "; options: " + options);
                 }
-                target.send(code, intent, resolvedType, allowlistToken, null,
+                target.send(code, intent, resolvedType, null, null,
                         requiredPermission, options);
             } catch (RemoteException e) {
             }
diff --git a/services/core/java/com/android/server/am/LowMemDetector.java b/services/core/java/com/android/server/am/LowMemDetector.java
index 8f79133..016d3cd 100644
--- a/services/core/java/com/android/server/am/LowMemDetector.java
+++ b/services/core/java/com/android/server/am/LowMemDetector.java
@@ -23,6 +23,7 @@
 import static com.android.internal.app.procstats.ProcessStats.ADJ_NOTHING;
 
 import android.annotation.IntDef;
+import android.os.Trace;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -90,17 +91,31 @@
     private native int waitForPressure();
 
     private final class LowMemThread extends Thread {
+        private boolean mIsTracingMemCriticalLow;
+
+        LowMemThread() {
+            super("LowMemThread");
+        }
+
         public void run() {
 
             while (true) {
                 // sleep waiting for a PSI event
                 int newPressureState = waitForPressure();
+                // PSI event detected
+                boolean isCriticalLowMemory = newPressureState == ADJ_MEM_FACTOR_CRITICAL;
+                if (isCriticalLowMemory && !mIsTracingMemCriticalLow) {
+                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "criticalLowMemory");
+                } else if (!isCriticalLowMemory && mIsTracingMemCriticalLow) {
+                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+                }
+                mIsTracingMemCriticalLow = isCriticalLowMemory;
                 if (newPressureState == -1) {
                     // epoll broke, tear this down
                     mAvailable = false;
                     break;
                 }
-                // got a PSI event? let's update lowmem info
+                // got an actual PSI event? let's update lowmem info
                 synchronized (mPressureStateLock) {
                     mPressureState = newPressureState;
                 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index e0e6cad..f04198e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -869,6 +869,8 @@
                                 ApplicationExitInfo.REASON_LOW_MEMORY,
                                 ApplicationExitInfo.SUBREASON_OOM_KILL,
                                 "oom");
+
+                            oomKill.logKillOccurred();
                         }
                     }
                 }
@@ -3255,6 +3257,17 @@
                 hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
         final ProcessStateRecord state = r.mState;
 
+        // Check if we should mark the processrecord for first launch after force-stopping
+        if ((r.getApplicationInfo().flags & ApplicationInfo.FLAG_STOPPED) != 0) {
+            final boolean wasPackageEverLaunched = mService.getPackageManagerInternal()
+                    .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
+            // If the package was launched in the past but is currently stopped, only then it
+            // should be considered as stopped after use. Do not mark it if it's the first launch.
+            if (wasPackageEverLaunched) {
+                r.setWasForceStopped(true);
+            }
+        }
+
         if (!isolated && !isSdkSandbox
                 && userId == UserHandle.USER_SYSTEM
                 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 940c58b..354f3d3 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -23,6 +23,7 @@
 import android.app.ProcessMemoryState.HostingComponentType;
 import android.content.pm.ApplicationInfo;
 import android.os.Debug;
+import android.os.Process;
 import android.os.SystemClock;
 import android.util.DebugUtils;
 import android.util.TimeUtils;
@@ -271,15 +272,17 @@
                         origBase.makeInactive();
                     }
                     final ApplicationInfo info = mApp.info;
+                    final int attributionUid = getUidForAttribution(mApp);
                     final ProcessState baseProcessTracker = tracker.getProcessStateLocked(
-                            info.packageName, info.uid, info.longVersionCode, mApp.processName);
+                            info.packageName, attributionUid, info.longVersionCode,
+                            mApp.processName);
                     setBaseProcessTracker(baseProcessTracker);
                     baseProcessTracker.makeActive();
                     pkgList.forEachPackage((pkgName, holder) -> {
                         if (holder.state != null && holder.state != origBase) {
                             holder.state.makeInactive();
                         }
-                        tracker.updateProcessStateHolderLocked(holder, pkgName, mApp.info.uid,
+                        tracker.updateProcessStateHolderLocked(holder, pkgName, attributionUid,
                                 mApp.info.longVersionCode, mApp.processName);
                         if (holder.state != baseProcessTracker) {
                             holder.state.makeActive();
@@ -536,7 +539,7 @@
                     tracker.reportCachedKill(pkgList.getPackageListLocked(), mLastCachedPss);
                     pkgList.forEachPackageProcessStats(holder ->
                             FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
-                                mApp.info.uid,
+                                getUidForAttribution(mApp),
                                 holder.state.getName(),
                                 holder.state.getPackage(),
                                 mLastCachedPss,
@@ -595,6 +598,21 @@
         tracker.mPendingMemState = -1;
     }
 
+    /**
+     * Returns the uid that should be used for attribution purposes in profiling / stats.
+     *
+     * In most cases this returns the uid of the process itself. For isolated processes though,
+     * since the process uid is dynamically allocated and can't easily be traced back to the app,
+     * for attribution we use the app package uid.
+     */
+    private static int getUidForAttribution(ProcessRecord processRecord) {
+        if (Process.isIsolatedUid(processRecord.uid)) {
+            return processRecord.info.uid;
+        } else {
+            return processRecord.uid;
+        }
+    }
+
     @GuardedBy("mProfilerLock")
     int getPid() {
         return mPid;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index f02b8c7..2c6e598 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -438,6 +438,9 @@
 
     final ProcessRecordNode[] mLinkedNodes = new ProcessRecordNode[NUM_NODE_TYPE];
 
+    /** Whether the app was launched from a stopped state and is being unstopped. */
+    volatile boolean mWasForceStopped;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startUptime, long startElapsedTime) {
         this.mStartUid = startUid;
@@ -1602,4 +1605,12 @@
     List<ProcessRecord> getLruProcessList() {
         return mService.mProcessList.getLruProcessesLOSP();
     }
+
+    public void setWasForceStopped(boolean stopped) {
+        mWasForceStopped = stopped;
+    }
+
+    public boolean wasForceStopped() {
+        return mWasForceStopped;
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index a165e88..f5f2b10 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -347,8 +347,10 @@
         mHasAboveClient = false;
         for (int i = mConnections.size() - 1; i >= 0; i--) {
             ConnectionRecord cr = mConnections.valueAt(i);
-            if (cr.binding.service.app.mServices != this
-                    && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
+
+            final boolean isSameProcess = cr.binding.service.app != null
+                    && cr.binding.service.app.mServices == this;
+            if (!isSameProcess && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
                 mHasAboveClient = true;
                 break;
             }
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index aa788eb..a57a785 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -145,6 +145,7 @@
         "media_drm",
         "media_solutions",
         "nfc",
+        "pdf_viewer",
         "pixel_audio_android",
         "pixel_system_sw_touch",
         "pixel_watch",
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index de4ad20..0dd579f 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -3387,7 +3387,7 @@
 
     }
 
-    private BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
+    BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
             @PowerWhitelistManager.ReasonCode int reasonCode) {
         long duration = 10_000;
         final ActivityManagerInternal amInternal =
diff --git a/services/core/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java
index 4f1df3f..70d4ad2 100644
--- a/services/core/java/com/android/server/display/DisplayAdapter.java
+++ b/services/core/java/com/android/server/display/DisplayAdapter.java
@@ -120,14 +120,14 @@
     }
 
     public static Display.Mode createMode(int width, int height, float refreshRate) {
-        return createMode(width, height, refreshRate, new float[0], new int[0]);
+        return createMode(width, height, refreshRate, refreshRate, new float[0], new int[0]);
     }
 
-    public static Display.Mode createMode(int width, int height, float refreshRate,
+    public static Display.Mode createMode(int width, int height, float refreshRate, float vsyncRate,
             float[] alternativeRefreshRates,
             @Display.HdrCapabilities.HdrType int[] supportedHdrTypes) {
         return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate,
-                alternativeRefreshRates, supportedHdrTypes);
+                vsyncRate, alternativeRefreshRates, supportedHdrTypes);
     }
 
     public interface Listener {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e5f01df..57b2c24 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1132,6 +1132,7 @@
                     new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE,
                             currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(),
                             overriddenInfo.refreshRateOverride,
+                            currentMode.getVsyncRate(),
                             new float[0], currentMode.getSupportedHdrTypes());
             overriddenInfo.modeId =
                     overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1]
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index e5d38cb..be3207d 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -319,10 +319,10 @@
                     SurfaceControl.DisplayMode other = displayModes[j];
                     boolean isAlternative = j != i && other.width == mode.width
                             && other.height == mode.height
-                            && other.refreshRate != mode.refreshRate
+                            && other.peakRefreshRate != mode.peakRefreshRate
                             && other.group == mode.group;
                     if (isAlternative) {
-                        alternativeRefreshRates.add(displayModes[j].refreshRate);
+                        alternativeRefreshRates.add(displayModes[j].peakRefreshRate);
                     }
                 }
                 Collections.sort(alternativeRefreshRates);
@@ -1360,7 +1360,7 @@
 
         DisplayModeRecord(SurfaceControl.DisplayMode mode,
                 float[] alternativeRefreshRates) {
-            mMode = createMode(mode.width, mode.height, mode.refreshRate,
+            mMode = createMode(mode.width, mode.height, mode.peakRefreshRate, mode.vsyncRate,
                     alternativeRefreshRates, mode.supportedHdrTypes);
         }
 
@@ -1375,7 +1375,9 @@
             return mMode.getPhysicalWidth() == mode.width
                     && mMode.getPhysicalHeight() == mode.height
                     && Float.floatToIntBits(mMode.getRefreshRate())
-                    == Float.floatToIntBits(mode.refreshRate);
+                            == Float.floatToIntBits(mode.peakRefreshRate)
+                    && Float.floatToIntBits(mMode.getVsyncRate())
+                            == Float.floatToIntBits(mode.vsyncRate);
         }
 
         public String toString() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3435e56..0c4ecbc 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -5529,6 +5529,42 @@
         return canAccess;
     }
 
+    @GuardedBy("ImfLock.class")
+    private void switchKeyboardLayoutLocked(int direction) {
+        final InputMethodInfo currentImi = mMethodMap.get(getSelectedMethodIdLocked());
+        if (currentImi == null) {
+            return;
+        }
+        final InputMethodSubtypeHandle currentSubtypeHandle =
+                InputMethodSubtypeHandle.of(currentImi, mCurrentSubtype);
+        final InputMethodSubtypeHandle nextSubtypeHandle =
+                mHardwareKeyboardShortcutController.onSubtypeSwitch(currentSubtypeHandle,
+                        direction > 0);
+        if (nextSubtypeHandle == null) {
+            return;
+        }
+        final InputMethodInfo nextImi = mMethodMap.get(nextSubtypeHandle.getImeId());
+        if (nextImi == null) {
+            return;
+        }
+
+        final int subtypeCount = nextImi.getSubtypeCount();
+        if (subtypeCount == 0) {
+            if (nextSubtypeHandle.equals(InputMethodSubtypeHandle.of(nextImi, null))) {
+                setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID);
+            }
+            return;
+        }
+
+        for (int i = 0; i < subtypeCount; ++i) {
+            if (nextSubtypeHandle.equals(
+                    InputMethodSubtypeHandle.of(nextImi, nextImi.getSubtypeAt(i)))) {
+                setInputMethodLocked(nextImi.getId(), i);
+                return;
+            }
+        }
+    }
+
     private void publishLocalService() {
         LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl());
     }
@@ -5734,38 +5770,7 @@
         @Override
         public void switchKeyboardLayout(int direction) {
             synchronized (ImfLock.class) {
-                final InputMethodInfo currentImi = mMethodMap.get(getSelectedMethodIdLocked());
-                if (currentImi == null) {
-                    return;
-                }
-                final InputMethodSubtypeHandle currentSubtypeHandle =
-                        InputMethodSubtypeHandle.of(currentImi, mCurrentSubtype);
-                final InputMethodSubtypeHandle nextSubtypeHandle =
-                        mHardwareKeyboardShortcutController.onSubtypeSwitch(currentSubtypeHandle,
-                                direction > 0);
-                if (nextSubtypeHandle == null) {
-                    return;
-                }
-                final InputMethodInfo nextImi = mMethodMap.get(nextSubtypeHandle.getImeId());
-                if (nextImi == null) {
-                    return;
-                }
-
-                final int subtypeCount = nextImi.getSubtypeCount();
-                if (subtypeCount == 0) {
-                    if (nextSubtypeHandle.equals(InputMethodSubtypeHandle.of(nextImi, null))) {
-                        setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID);
-                    }
-                    return;
-                }
-
-                for (int i = 0; i < subtypeCount; ++i) {
-                    if (nextSubtypeHandle.equals(
-                            InputMethodSubtypeHandle.of(nextImi, nextImi.getSubtypeAt(i)))) {
-                        setInputMethodLocked(nextImi.getId(), i);
-                        return;
-                    }
-                }
+                switchKeyboardLayoutLocked(direction);
             }
         }
 
@@ -6767,5 +6772,21 @@
         public void resetStylusHandwriting(int requestId) {
             mImms.resetStylusHandwriting(requestId);
         }
+
+        @BinderThread
+        @Override
+        public void switchKeyboardLayoutAsync(int direction) {
+            synchronized (ImfLock.class) {
+                if (!mImms.calledWithValidTokenLocked(mToken)) {
+                    return;
+                }
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    mImms.switchKeyboardLayoutLocked(direction);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 74b7f08..323cdc5 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -474,13 +474,14 @@
                 // If we have a GNSS provider override, add the hardware provider as a standalone
                 // option for use by apps with the correct permission. Note the GNSS HAL can only
                 // support a single client, so mGnssManagerService.getGnssLocationProvider() can
-                // only be installed with a single provider.
+                // only be installed with a single provider. Locations from this provider won't
+                // be reported through the passive provider.
                 LocationProviderManager gnssHardwareManager =
                         new LocationProviderManager(
                                 mContext,
                                 mInjector,
                                 GPS_HARDWARE_PROVIDER,
-                                mPassiveManager,
+                                /*passiveManager=*/ null,
                                 Collections.singletonList(Manifest.permission.LOCATION_HARDWARE));
                 addLocationProviderManager(
                         gnssHardwareManager, mGnssManagerService.getGnssLocationProvider());
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index ce35a61..58927d1 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -76,7 +76,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
@@ -385,10 +384,12 @@
             if (mProjectionGrant != null) {
                 // Cache the session details.
                 mProjectionGrant.mSession = incomingSession;
-                mMediaProjectionMetricsLogger.notifyProjectionStateChange(
-                        mProjectionGrant.uid,
-                        FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS,
-                        FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+                if (incomingSession != null) {
+                    // Only log in progress when session is not null.
+                    // setContentRecordingSession is called with a null session for the stop case.
+                    mMediaProjectionMetricsLogger.logInProgress(
+                            mProjectionGrant.uid, incomingSession.getTargetUid());
+                }
                 dispatchSessionSet(mProjectionGrant.getProjectionInfo(), incomingSession);
             }
             return true;
@@ -463,6 +464,16 @@
         mMediaProjectionMetricsLogger.logInitiated(hostUid, sessionCreationSource);
     }
 
+    @VisibleForTesting
+    void notifyPermissionRequestDisplayed(int hostUid) {
+        mMediaProjectionMetricsLogger.logPermissionRequestDisplayed(hostUid);
+    }
+
+    @VisibleForTesting
+    void notifyAppSelectorDisplayed(int hostUid) {
+        mMediaProjectionMetricsLogger.logAppSelectorDisplayed(hostUid);
+    }
+
     /**
      * Handles result of dialog shown from
      * {@link BinderService#buildReviewGrantedConsentIntentLocked()}.
@@ -866,6 +877,30 @@
         }
 
         @Override // Binder call
+        @EnforcePermission(MANAGE_MEDIA_PROJECTION)
+        public void notifyPermissionRequestDisplayed(int hostUid) {
+            notifyPermissionRequestDisplayed_enforcePermission();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                MediaProjectionManagerService.this.notifyPermissionRequestDisplayed(hostUid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
+        @EnforcePermission(MANAGE_MEDIA_PROJECTION)
+        public void notifyAppSelectorDisplayed(int hostUid) {
+            notifyAppSelectorDisplayed_enforcePermission();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                MediaProjectionManagerService.this.notifyAppSelectorDisplayed(hostUid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java
index c8b932a..55a30bf 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java
@@ -16,7 +16,15 @@
 
 package com.android.server.media.projection;
 
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED;
+
 import android.content.Context;
+import android.util.Log;
 
 import com.android.internal.util.FrameworkStatsLog;
 
@@ -24,6 +32,8 @@
 
 /** Class for emitting logs describing a MediaProjection session. */
 public class MediaProjectionMetricsLogger {
+    private static final String TAG = "MediaProjectionMetricsLogger";
+
     private static final int TARGET_UID_UNKNOWN = -2;
     private static final int TIME_SINCE_LAST_ACTIVE_UNKNOWN = -1;
 
@@ -75,6 +85,7 @@
      *     </ul>
      */
     public void logInitiated(int hostUid, int sessionCreationSource) {
+        Log.d(TAG, "logInitiated");
         Duration durationSinceLastActiveSession = mTimestampStore.timeSinceLastActiveSession();
         int timeSinceLastActiveInSeconds =
                 durationSinceLastActiveSession == null
@@ -82,26 +93,85 @@
                         : (int) durationSinceLastActiveSession.toSeconds();
         write(
                 mSessionIdGenerator.createAndGetNewSessionId(),
-                FrameworkStatsLog
-                        .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED,
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED,
                 hostUid,
                 TARGET_UID_UNKNOWN,
                 timeSinceLastActiveInSeconds,
                 sessionCreationSource);
     }
 
-    /** Logs that the capturing stopped, either normally or because of error. */
-    public void logStopped(int hostUid, int targetUid) {
+    /**
+     * Logs that the user entered the setup flow and permission dialog is displayed. This state is
+     * not sent when the permission is already granted and we skipped showing the permission dialog.
+     *
+     * @param hostUid UID of the package that initiates MediaProjection.
+     */
+    public void logPermissionRequestDisplayed(int hostUid) {
+        Log.d(TAG, "logPermissionRequestDisplayed");
         write(
                 mSessionIdGenerator.getCurrentSessionId(),
-                FrameworkStatsLog
-                        .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED,
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED,
+                hostUid,
+                TARGET_UID_UNKNOWN,
+                TIME_SINCE_LAST_ACTIVE_UNKNOWN,
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    /**
+     * Logs that the app selector dialog is shown for the user.
+     *
+     * @param hostUid UID of the package that initiates MediaProjection.
+     */
+    public void logAppSelectorDisplayed(int hostUid) {
+        Log.d(TAG, "logAppSelectorDisplayed");
+        write(
+                mSessionIdGenerator.getCurrentSessionId(),
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED,
+                hostUid,
+                TARGET_UID_UNKNOWN,
+                TIME_SINCE_LAST_ACTIVE_UNKNOWN,
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    /**
+     * Logs that the virtual display is created and capturing the selected region begins.
+     *
+     * @param hostUid UID of the package that initiates MediaProjection.
+     * @param targetUid UID of the package that is captured if selected.
+     */
+    public void logInProgress(int hostUid, int targetUid) {
+        Log.d(TAG, "logInProgress");
+        write(
+                mSessionIdGenerator.getCurrentSessionId(),
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS,
                 hostUid,
                 targetUid,
                 TIME_SINCE_LAST_ACTIVE_UNKNOWN,
-                FrameworkStatsLog
-                        .MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
-        mTimestampStore.registerActiveSessionEnded();
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    /**
+     * Logs that the capturing stopped, either normally or because of error.
+     *
+     * @param hostUid UID of the package that initiates MediaProjection.
+     * @param targetUid UID of the package that is captured if selected.
+     */
+    public void logStopped(int hostUid, int targetUid) {
+        boolean wasCaptureInProgress =
+                mPreviousState
+                        == MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS;
+        Log.d(TAG, "logStopped: wasCaptureInProgress=" + wasCaptureInProgress);
+        write(
+                mSessionIdGenerator.getCurrentSessionId(),
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED,
+                hostUid,
+                targetUid,
+                TIME_SINCE_LAST_ACTIVE_UNKNOWN,
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+
+        if (wasCaptureInProgress) {
+            mTimestampStore.registerActiveSessionEnded();
+        }
     }
 
     public void notifyProjectionStateChange(int hostUid, int state, int sessionCreationSource) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 2967818..a5c5ae2 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.server.pm;
 
-import static android.content.pm.Flags.preventSdkLibApp;
+import static android.content.pm.Flags.disallowSdkLibsToBeApps;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
@@ -996,7 +996,7 @@
                     }
                     final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
                     final boolean isSdkLibrary = packageToScan.isSdkLibrary();
-                    if (isApex || (isSdkLibrary && preventSdkLibApp())) {
+                    if (isApex || (isSdkLibrary && disallowSdkLibsToBeApps())) {
                         request.getScannedPackageSetting().setAppId(Process.INVALID_UID);
                     } else {
                         createdAppId.put(packageName, optimisticallyRegisterAppId(request));
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index a161e8c..1135466 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -65,6 +65,7 @@
 import android.content.pm.LauncherActivityInfoInternal;
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.LauncherUserInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageManager;
@@ -1377,6 +1378,25 @@
         }
 
         @Override
+        public @Nullable LauncherUserInfo getLauncherUserInfo(@NonNull UserHandle user) {
+            // Only system launchers, which have access to recents should have access to this API.
+            // TODO(b/303803157): Add the new permission check if we decide to have one.
+            if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
+                throw new SecurityException("Caller is not the recents app");
+            }
+            if (!canAccessProfile(user.getIdentifier(),
+                    "Can't access LauncherUserInfo for another user")) {
+                return null;
+            }
+            long ident = injectClearCallingIdentity();
+            try {
+                return mUserManagerInternal.getLauncherUserInfo(user.getIdentifier());
+            } finally {
+                injectRestoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
         public void startActivityAsUser(IApplicationThread caller, String callingPackage,
                 String callingFeatureId, ComponentName component, Rect sourceBounds,
                 Bundle opts, UserHandle user) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 0fb1f7a..781e5f8 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -38,6 +38,8 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.pm.VersionedPackage;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -48,6 +50,7 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.ParcelableException;
+import android.os.Process;
 import android.os.SELinux;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -162,15 +165,13 @@
                         });
     }
 
-    /**
-     * Creates archived state for the package and user.
-     */
-    public CompletableFuture<ArchiveState> createArchiveState(String packageName, int userId)
+    /** Creates archived state for the package and user. */
+    private CompletableFuture<ArchiveState> createArchiveState(String packageName, int userId)
             throws PackageManager.NameNotFoundException {
         PackageStateInternal ps = getPackageState(packageName, mPm.snapshotComputer(),
                 Binder.getCallingUid(), userId);
         String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
-        verifyInstaller(responsibleInstallerPackage);
+        verifyInstaller(responsibleInstallerPackage, userId);
 
         List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps.getPackageName(),
                 userId);
@@ -268,27 +269,34 @@
         return iconFile.toPath();
     }
 
-    private void verifyInstaller(String installerPackage)
+    private void verifyInstaller(String installerPackage, int userId)
             throws PackageManager.NameNotFoundException {
         if (TextUtils.isEmpty(installerPackage)) {
             throw new PackageManager.NameNotFoundException("No installer found");
         }
-        if (!verifySupportsUnarchival(installerPackage)) {
+        // Allow shell for easier development.
+        if ((Binder.getCallingUid() != Process.SHELL_UID)
+                && !verifySupportsUnarchival(installerPackage, userId)) {
             throw new PackageManager.NameNotFoundException("Installer does not support unarchival");
         }
     }
 
     /**
-     * @return true if installerPackage support unarchival:
-     * - has an action Intent.ACTION_UNARCHIVE_PACKAGE,
-     * - has permissions to install packages.
+     * Returns true if {@code installerPackage} supports unarchival being able to handle
+     * {@link Intent#ACTION_UNARCHIVE_PACKAGE}
      */
-    public boolean verifySupportsUnarchival(String installerPackage) {
-        // TODO(b/278553670) Check if installerPackage supports unarchival.
+    public boolean verifySupportsUnarchival(String installerPackage, int userId) {
         if (TextUtils.isEmpty(installerPackage)) {
             return false;
         }
-        return true;
+
+        Intent intent = new Intent(Intent.ACTION_UNARCHIVE_PACKAGE).setPackage(installerPackage);
+
+        ParceledListSlice<ResolveInfo> intentReceivers =
+                Binder.withCleanCallingIdentity(
+                        () -> mPm.queryIntentReceivers(mPm.snapshotComputer(),
+                                intent, /* resolvedType= */ null, /* flags= */ 0, userId));
+        return intentReceivers != null && !intentReceivers.getList().isEmpty();
     }
 
     void requestUnarchive(
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d0e5f96..5dc7dab 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3445,7 +3445,7 @@
             }
 
             if (!mPm.mInstallerService.mPackageArchiver.verifySupportsUnarchival(
-                    getInstallSource().mInstallerPackageName)) {
+                    getInstallSource().mInstallerPackageName, userId)) {
                 throw new PackageManagerException(
                         PackageManager.INSTALL_FAILED_SESSION_INVALID,
                         "Installer has to support unarchival in order to install archived "
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 29d99a73..e8cebef 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -120,8 +120,8 @@
             return packageNames;
         }
 
-        final SuspendParams newSuspendParams =
-                new SuspendParams(dialogInfo, appExtras, launcherExtras, quarantined);
+        final SuspendParams newSuspendParams = suspended
+                ? new SuspendParams(dialogInfo, appExtras, launcherExtras, quarantined) : null;
 
         final List<String> unmodifiablePackages = new ArrayList<>(packageNames.length);
 
@@ -156,8 +156,8 @@
 
             final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
                     packageState.getUserStateOrDefault(userId).getSuspendParams();
-            SuspendParams oldSuspendParams = suspendParamsMap == null
-                    ? null : suspendParamsMap.get(packageName);
+            final SuspendParams oldSuspendParams = suspendParamsMap == null
+                    ? null : suspendParamsMap.get(callingPackage);
             boolean changed = !Objects.equals(oldSuspendParams, newSuspendParams);
 
             if (suspended && !changed) {
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 04cd183..0e7ce2e 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Context;
+import android.content.pm.LauncherUserInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.UserProperties;
 import android.graphics.Bitmap;
@@ -407,6 +408,11 @@
     public abstract @NonNull UserInfo[] getUserInfos();
 
     /**
+     * Gets a {@link LauncherUserInfo} for the given {@code userId}, or {@code null} if not found.
+     */
+    public abstract @Nullable LauncherUserInfo getLauncherUserInfo(@UserIdInt int userId);
+
+    /**
      * Sets all default cross profile intent filters between {@code parentUserId} and
      * {@code profileUserId}.
      */
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7331bc1..154ee6e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -62,6 +62,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.LauncherUserInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
@@ -7153,6 +7154,24 @@
         }
 
         @Override
+        public @Nullable LauncherUserInfo getLauncherUserInfo(@UserIdInt int userId) {
+            UserInfo userInfo;
+            synchronized (mUsersLock) {
+                userInfo = getUserInfoLU(userId);
+            }
+            if (userInfo != null) {
+                final UserTypeDetails userDetails = getUserTypeDetails(userInfo);
+                final LauncherUserInfo uiInfo = new LauncherUserInfo.Builder(
+                        userDetails.getName(),
+                        userInfo.serialNumber)
+                        .build();
+                return uiInfo;
+            } else {
+                return null;
+            }
+        }
+
+        @Override
         public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
             int state;
             synchronized (mUserStates) {
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 61e96ca..2ad8bcf 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -1016,8 +1016,8 @@
             return;
         }
 
-        if (android.content.pm.Flags.nullableDataDir()
-                && !state.isInstalled() && !state.dataExists()) {
+        if (!state.isInstalled() && !state.dataExists()
+                && android.content.pm.Flags.nullableDataDir()) {
             // The data dir has been deleted
             output.dataDir = null;
             return;
@@ -1065,8 +1065,8 @@
             return;
         }
 
-        if (android.content.pm.Flags.nullableDataDir()
-                && !state.isInstalled() && !state.dataExists()) {
+        if (!state.isInstalled() && !state.dataExists()
+                && android.content.pm.Flags.nullableDataDir()) {
             // The data dir has been deleted
             output.dataDir = null;
             return;
@@ -1113,9 +1113,9 @@
             return Environment.getDataSystemDirectory();
         }
 
-        if (android.content.pm.Flags.nullableDataDir()
-                && !ps.getUserStateOrDefault(userId).isInstalled()
-                && !ps.getUserStateOrDefault(userId).dataExists()) {
+        if (!ps.getUserStateOrDefault(userId).isInstalled()
+                && !ps.getUserStateOrDefault(userId).dataExists()
+                && android.content.pm.Flags.nullableDataDir()) {
             // The app has been uninstalled for the user and the data dir has been deleted
             return null;
         }
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 46121dc..8240c47 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -18,7 +18,7 @@
 
 import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.Flags.preventSdkLibApp;
+import static android.content.pm.Flags.disallowSdkLibsToBeApps;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
@@ -404,7 +404,7 @@
 
         try {
             final File baseApk = new File(lite.getBaseApkPath());
-            boolean shouldSkipComponents = lite.isIsSdkLibrary() && preventSdkLibApp();
+            boolean shouldSkipComponents = lite.isIsSdkLibrary() && disallowSdkLibsToBeApps();
             final ParseResult<ParsingPackage> result = parseBaseApk(input, baseApk,
                     lite.getPath(), assetLoader, flags, shouldSkipComponents);
             if (result.isError()) {
@@ -458,7 +458,7 @@
         final PackageLite lite = liteResult.getResult();
         final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
         try {
-            boolean shouldSkipComponents =  lite.isIsSdkLibrary() && preventSdkLibApp();
+            boolean shouldSkipComponents =  lite.isIsSdkLibrary() && disallowSdkLibsToBeApps();
             final ParseResult<ParsingPackage> result = parseBaseApk(input,
                     apkFile,
                     apkFile.getCanonicalPath(),
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7c0fc99..b439681 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2478,7 +2478,7 @@
                 com.android.internal.R.integer.config_keyguardDrawnTimeout);
         mKeyguardDelegate = injector.getKeyguardServiceDelegate();
         initKeyCombinationRules();
-        initSingleKeyGestureRules();
+        initSingleKeyGestureRules(injector.getLooper());
         mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
     }
 
@@ -2749,8 +2749,8 @@
         }
     }
 
-    private void initSingleKeyGestureRules() {
-        mSingleKeyGestureDetector = SingleKeyGestureDetector.get(mContext);
+    private void initSingleKeyGestureRules(Looper looper) {
+        mSingleKeyGestureDetector = SingleKeyGestureDetector.get(mContext, looper);
         mSingleKeyGestureDetector.addRule(new PowerKeyRule());
         if (hasLongPressOnBackBehavior()) {
             mSingleKeyGestureDetector.addRule(new BackKeyRule());
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index 5fc0637..047555a 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -40,6 +40,7 @@
     private static final int MSG_KEY_LONG_PRESS = 0;
     private static final int MSG_KEY_VERY_LONG_PRESS = 1;
     private static final int MSG_KEY_DELAYED_PRESS = 2;
+    private static final int MSG_KEY_UP = 3;
 
     private int mKeyPressCounter;
     private boolean mBeganFromNonInteractive = false;
@@ -144,6 +145,13 @@
          *  Callback when very long press has been detected.
          */
         void onVeryLongPress(long eventTime) {}
+        /**
+         * Callback executed upon each key up event that hasn't been processed by long press.
+         *
+         * @param eventTime the timestamp of this event.
+         * @param pressCount the number of presses detected leading up to this key up event.
+         */
+        void onKeyUp(long eventTime, int pressCount) {}
 
         @Override
         public String toString() {
@@ -171,8 +179,8 @@
         }
     }
 
-    static SingleKeyGestureDetector get(Context context) {
-        SingleKeyGestureDetector detector = new SingleKeyGestureDetector();
+    static SingleKeyGestureDetector get(Context context, Looper looper) {
+        SingleKeyGestureDetector detector = new SingleKeyGestureDetector(looper);
         sDefaultLongPressTimeout = context.getResources().getInteger(
                 com.android.internal.R.integer.config_globalActionsKeyTimeout);
         sDefaultVeryLongPressTimeout = context.getResources().getInteger(
@@ -180,8 +188,8 @@
         return detector;
     }
 
-    private SingleKeyGestureDetector() {
-        mHandler = new KeyHandler();
+    private SingleKeyGestureDetector(Looper looper) {
+        mHandler = new KeyHandler(looper);
     }
 
     void addRule(SingleKeyRule rule) {
@@ -330,6 +338,13 @@
         }
 
         if (event.getKeyCode() == mActiveRule.mKeyCode) {
+            // key-up action should always be triggered if not processed by long press.
+            Message msgKeyUp =
+                    mHandler.obtainMessage(
+                            MSG_KEY_UP, mActiveRule.mKeyCode, mKeyPressCounter, mActiveRule);
+            msgKeyUp.setAsynchronous(true);
+            mHandler.sendMessage(msgKeyUp);
+
             // Directly trigger short press when max count is 1.
             if (mActiveRule.getMaxMultiPressCount() == 1) {
                 if (DEBUG) {
@@ -402,8 +417,8 @@
     }
 
     private class KeyHandler extends Handler {
-        KeyHandler() {
-            super(Looper.myLooper());
+        KeyHandler(Looper looper) {
+            super(looper);
         }
 
         @Override
@@ -417,6 +432,12 @@
             final int keyCode = msg.arg1;
             final int pressCount = msg.arg2;
             switch(msg.what) {
+                case MSG_KEY_UP:
+                    if (DEBUG) {
+                        Log.i(TAG, "Detect key up " + KeyEvent.keyCodeToString(keyCode));
+                    }
+                    rule.onKeyUp(mLastDownTime, pressCount);
+                    break;
                 case MSG_KEY_LONG_PRESS:
                     if (DEBUG) {
                         Log.i(TAG, "Detect long press " + KeyEvent.keyCodeToString(keyCode));
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9fa5ed2..fd8f6bf 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3055,7 +3055,7 @@
 
     @Override
     boolean providesOrientation() {
-        return mStyleFillsParent;
+        return mStyleFillsParent || mOccludesParent;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivitySnapshotController.java b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
index 01b8bf7..52ab9b8 100644
--- a/services/core/java/com/android/server/wm/ActivitySnapshotController.java
+++ b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
@@ -539,7 +539,7 @@
         if (usf != null) {
             mUserSavedFiles.get(userId).remove(code);
             mSavedFilesInOrder.remove(usf);
-            mPersister.removeSnap(code, userId);
+            mPersister.removeSnapshot(code, userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java b/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
index d604402..5db02df 100644
--- a/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/BaseAppSnapshotPersister.java
@@ -58,7 +58,7 @@
      * @param id The id of task that has been removed.
      * @param userId The id of the user the task belonged to.
      */
-    void removeSnap(int id, int userId) {
+    void removeSnapshot(int id, int userId) {
         synchronized (mLock) {
             mSnapshotPersistQueue.sendToQueueLocked(mSnapshotPersistQueue
                     .createDeleteWriteQueueItem(id, userId, mPersistInfoProvider));
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 823fbc9..2fabb0e 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -29,7 +29,7 @@
  */
 public abstract class Dimmer {
 
-    static final boolean DIMMER_REFACTOR = Flags.dimmerRefactor();
+    static final boolean DIMMER_REFACTOR = Flags.introduceSmootherDimmer();
 
     /**
      * The {@link WindowContainer} that our Dims are bounded to. We may be dimming on behalf of the
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b7b5c2af..4fa6e29 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -937,6 +937,7 @@
                 // so we still request the window to resize if the current frame is empty.
                 if (!w.getFrame().isEmpty()) {
                     w.updateLastFrames();
+                    mWmService.mFrameChangingWindows.remove(w);
                 }
                 w.onResizeHandled();
             }
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index f9fa9e6..f6aad4c 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -36,7 +36,10 @@
 
 import com.android.server.UiThread;
 
+import java.util.function.BooleanSupplier;
+import java.util.function.DoubleSupplier;
 import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
 import java.util.function.Supplier;
 
 /**
@@ -50,12 +53,12 @@
 
     private final Supplier<SurfaceControl.Builder> mSurfaceControlFactory;
     private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
-    private final Supplier<Boolean> mAreCornersRounded;
+    private final BooleanSupplier mAreCornersRounded;
     private final Supplier<Color> mColorSupplier;
     // Parameters for "blurred wallpaper" letterbox background.
-    private final Supplier<Boolean> mHasWallpaperBackgroundSupplier;
-    private final Supplier<Integer> mBlurRadiusSupplier;
-    private final Supplier<Float> mDarkScrimAlphaSupplier;
+    private final BooleanSupplier mHasWallpaperBackgroundSupplier;
+    private final IntSupplier mBlurRadiusSupplier;
+    private final DoubleSupplier mDarkScrimAlphaSupplier;
     private final Supplier<SurfaceControl> mParentSurfaceSupplier;
 
     private final Rect mOuter = new Rect();
@@ -82,11 +85,11 @@
      */
     public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory,
             Supplier<SurfaceControl.Transaction> transactionFactory,
-            Supplier<Boolean> areCornersRounded,
+            BooleanSupplier areCornersRounded,
             Supplier<Color> colorSupplier,
-            Supplier<Boolean> hasWallpaperBackgroundSupplier,
-            Supplier<Integer> blurRadiusSupplier,
-            Supplier<Float> darkScrimAlphaSupplier,
+            BooleanSupplier hasWallpaperBackgroundSupplier,
+            IntSupplier blurRadiusSupplier,
+            DoubleSupplier darkScrimAlphaSupplier,
             IntConsumer doubleTapCallbackX,
             IntConsumer doubleTapCallbackY,
             Supplier<SurfaceControl> parentSurface) {
@@ -247,7 +250,7 @@
      * Returns {@code true} when using {@link #mFullWindowSurface} instead of {@link mSurfaces}.
      */
     private boolean useFullWindowSurface() {
-        return mAreCornersRounded.get() || mHasWallpaperBackgroundSupplier.get();
+        return mAreCornersRounded.getAsBoolean() || mHasWallpaperBackgroundSupplier.getAsBoolean();
     }
 
     private final class TapEventReceiver extends InputEventReceiver {
@@ -424,7 +427,7 @@
                         mSurfaceFrameRelative.height());
                 t.reparent(mSurface, mParentSurface);
 
-                mHasWallpaperBackground = mHasWallpaperBackgroundSupplier.get();
+                mHasWallpaperBackground = mHasWallpaperBackgroundSupplier.getAsBoolean();
                 updateAlphaAndBlur(t);
 
                 t.show(mSurface);
@@ -445,17 +448,17 @@
                 t.setBackgroundBlurRadius(mSurface, 0);
                 return;
             }
-            final float alpha = mDarkScrimAlphaSupplier.get();
+            final float alpha = (float) mDarkScrimAlphaSupplier.getAsDouble();
             t.setAlpha(mSurface, alpha);
 
             // Translucent dark scrim can be shown without blur.
-            if (mBlurRadiusSupplier.get() <= 0) {
+            if (mBlurRadiusSupplier.getAsInt() <= 0) {
                 // Removing pre-exesting blur
                 t.setBackgroundBlurRadius(mSurface, 0);
                 return;
             }
 
-            t.setBackgroundBlurRadius(mSurface, mBlurRadiusSupplier.get());
+            t.setBackgroundBlurRadius(mSurface, mBlurRadiusSupplier.getAsInt());
         }
 
         private float[] getRgbColorArray() {
@@ -472,7 +475,7 @@
                     // and mParentSurface may never be updated in applySurfaceChanges but this
                     // doesn't mean that update is needed.
                     || !mSurfaceFrameRelative.isEmpty()
-                    && (mHasWallpaperBackgroundSupplier.get() != mHasWallpaperBackground
+                    && (mHasWallpaperBackgroundSupplier.getAsBoolean() != mHasWallpaperBackground
                     || !mColorSupplier.get().equals(mColor)
                     || mParentSurfaceSupplier.get() != mParentSurface);
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 7a442e7..2281395 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -847,6 +847,7 @@
         }
 
         handleResizingWindows();
+        clearFrameChangingWindows();
 
         if (mWmService.mDisplayFrozen) {
             ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -1015,6 +1016,17 @@
     }
 
     /**
+     * Clears frame changing windows after handling moving and resizing windows.
+     */
+    private void clearFrameChangingWindows() {
+        final ArrayList<WindowState> frameChangingWindows = mWmService.mFrameChangingWindows;
+        for (int i = frameChangingWindows.size() - 1; i >= 0; i--) {
+            frameChangingWindows.get(i).updateLastFrames();
+        }
+        frameChangingWindows.clear();
+    }
+
+    /**
      * @param w        WindowState this method is applied to.
      * @param obscured True if there is a window on top of this obscuring the display.
      * @param syswin   System window?
diff --git a/services/core/java/com/android/server/wm/SnapshotController.java b/services/core/java/com/android/server/wm/SnapshotController.java
index f68e392..2be2a1a 100644
--- a/services/core/java/com/android/server/wm/SnapshotController.java
+++ b/services/core/java/com/android/server/wm/SnapshotController.java
@@ -26,6 +26,7 @@
 
 import android.os.Trace;
 import android.view.WindowManager;
+import android.window.TaskSnapshot;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -126,6 +127,18 @@
         }
         mActivitySnapshotController.handleTransitionFinish(windows);
         mActivitySnapshotController.endSnapshotProcess();
+        // Remove task snapshot if it is visible at the end of transition.
+        for (int i = changeInfos.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = changeInfos.get(i).mContainer;
+            final Task task = wc.asTask();
+            if (task != null && wc.isVisibleRequested()) {
+                final TaskSnapshot snapshot = mTaskSnapshotController.getSnapshot(task.mTaskId,
+                        task.mUserId, false /* restoreFromDisk */, false /* isLowResolution */);
+                if (snapshot != null) {
+                    mTaskSnapshotController.removeAndDeleteSnapshot(task.mTaskId, task.mUserId);
+                }
+            }
+        }
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4922e90..6c31e3e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -199,7 +199,6 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.uri.NeededUriGrants;
-import com.android.window.flags.Flags;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -241,7 +240,6 @@
     private static final String ATTR_ROOT_AFFINITY = "root_affinity";
     private static final String ATTR_ROOTHASRESET = "root_has_reset";
     private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
-    private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
     private static final String ATTR_USERID = "user_id";
     private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
     private static final String ATTR_EFFECTIVE_UID = "effective_uid";
@@ -344,7 +342,6 @@
                             // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
     boolean autoRemoveRecents;  // If true, we should automatically remove the task from
                                 // recents when activity finishes
-    boolean askedCompatMode;// Have asked the user about compat mode for this task.
     private boolean mHasBeenVisible; // Set if any activities in the task have been visible
 
     String stringName;      // caching of toString() result.
@@ -617,7 +614,7 @@
     private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
             Intent _affinityIntent, String _affinity, String _rootAffinity,
             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
-            boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid,
+            boolean _autoRemoveRecents, int _userId, int _effectiveUid,
             String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity,
             TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData,
             int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid,
@@ -652,7 +649,6 @@
         rootWasReset = _rootWasReset;
         isAvailable = true;
         autoRemoveRecents = _autoRemoveRecents;
-        askedCompatMode = _askedCompatMode;
         mUserSetupComplete = userSetupComplete;
         effectiveUid = _effectiveUid;
         touchActiveTime();
@@ -1333,7 +1329,7 @@
 
         clearRootProcess();
 
-        mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
+        mAtmService.mWindowManager.mTaskSnapshotController.removeAndDeleteSnapshot(
                 mTaskId, mUserId);
     }
 
@@ -3304,7 +3300,7 @@
         // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
         // If true, we want to get the Dimmer from the level above since we don't want to animate
         // the dim with the Task.
-        if (!isRootTask() || (Flags.dimmerRefactor() && isTranslucentAndVisible())
+        if (!isRootTask() || (Dimmer.DIMMER_REFACTOR && isTranslucentAndVisible())
                 || isTranslucent(null)) {
             return super.getDimmer();
         }
@@ -3768,8 +3764,8 @@
             pw.println(")");
         }
         pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
-        if (!askedCompatMode || !inRecents || !isAvailable) {
-            pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
+        if (!inRecents || !isAvailable) {
+            pw.print(prefix);
             pw.print(" inRecents="); pw.print(inRecents);
             pw.print(" isAvailable="); pw.println(isAvailable);
         }
@@ -3877,7 +3873,6 @@
         }
         out.attributeBoolean(null, ATTR_ROOTHASRESET, rootWasReset);
         out.attributeBoolean(null, ATTR_AUTOREMOVERECENTS, autoRemoveRecents);
-        out.attributeBoolean(null, ATTR_ASKEDCOMPATMODE, askedCompatMode);
         out.attributeInt(null, ATTR_USERID, mUserId);
         out.attributeBoolean(null, ATTR_USER_SETUP_COMPLETE, mUserSetupComplete);
         out.attributeInt(null, ATTR_EFFECTIVE_UID, effectiveUid);
@@ -3975,7 +3970,6 @@
         String windowLayoutAffinity = null;
         boolean rootHasReset = false;
         boolean autoRemoveRecents = false;
-        boolean askedCompatMode = false;
         int taskType = 0;
         int userId = 0;
         boolean userSetupComplete = true;
@@ -4036,9 +4030,6 @@
                 case ATTR_AUTOREMOVERECENTS:
                     autoRemoveRecents = Boolean.parseBoolean(attrValue);
                     break;
-                case ATTR_ASKEDCOMPATMODE:
-                    askedCompatMode = Boolean.parseBoolean(attrValue);
-                    break;
                 case ATTR_USERID:
                     userId = Integer.parseInt(attrValue);
                     break;
@@ -4192,7 +4183,6 @@
                 .setOrigActivity(origActivity)
                 .setRootWasReset(rootHasReset)
                 .setAutoRemoveRecents(autoRemoveRecents)
-                .setAskedCompatMode(askedCompatMode)
                 .setUserId(userId)
                 .setEffectiveUid(effectiveUid)
                 .setLastDescription(lastDescription)
@@ -6269,7 +6259,6 @@
         private ComponentName mOrigActivity;
         private boolean mRootWasReset;
         private boolean mAutoRemoveRecents;
-        private boolean mAskedCompatMode;
         private int mUserId;
         private int mEffectiveUid;
         private String mLastDescription;
@@ -6524,11 +6513,6 @@
             return this;
         }
 
-        private Builder setAskedCompatMode(boolean askedCompatMode) {
-            mAskedCompatMode = askedCompatMode;
-            return this;
-        }
-
         private Builder setAffinityIntent(Intent affinityIntent) {
             mAffinityIntent = affinityIntent;
             return this;
@@ -6661,7 +6645,7 @@
         Task buildInner() {
             return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity,
                     mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents,
-                    mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,
+                    mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,
                     mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData,
                     mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid,
                     mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 906b3b5..82d3424 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -103,7 +103,6 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.am.HostingRecord;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.window.flags.Flags;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -210,7 +209,7 @@
      */
     int mMinHeight;
 
-    Dimmer mDimmer = Flags.dimmerRefactor()
+    Dimmer mDimmer = Dimmer.DIMMER_REFACTOR
             ? new SmoothDimmer(this) : new LegacyDimmer(this);
 
     /** Apply the dim layer on the embedded TaskFragment. */
@@ -391,41 +390,6 @@
 
     private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
             new EnsureActivitiesVisibleHelper(this);
-    private final EnsureVisibleActivitiesConfigHelper mEnsureVisibleActivitiesConfigHelper =
-            new EnsureVisibleActivitiesConfigHelper();
-    private class EnsureVisibleActivitiesConfigHelper implements Predicate<ActivityRecord> {
-        private boolean mUpdateConfig;
-        private boolean mPreserveWindow;
-        private boolean mBehindFullscreen;
-
-        void reset(boolean preserveWindow) {
-            mPreserveWindow = preserveWindow;
-            mUpdateConfig = false;
-            mBehindFullscreen = false;
-        }
-
-        void process(ActivityRecord start, boolean preserveWindow) {
-            if (start == null || !start.isVisibleRequested()) {
-                return;
-            }
-            reset(preserveWindow);
-            forAllActivities(this, start, true /* includeBoundary */,
-                    true /* traverseTopToBottom */);
-
-            if (mUpdateConfig) {
-                // Ensure the resumed state of the focus activity if we updated the configuration of
-                // any activity.
-                mRootWindowContainer.resumeFocusedTasksTopActivities();
-            }
-        }
-
-        @Override
-        public boolean test(ActivityRecord r) {
-            mUpdateConfig |= r.ensureActivityConfiguration(0 /*globalChanges*/, mPreserveWindow);
-            mBehindFullscreen |= r.occludesParent();
-            return mBehindFullscreen;
-        }
-    }
 
     /** Creates an embedded task fragment. */
     TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken,
@@ -2163,13 +2127,6 @@
         return getTask() != null ? getTask().mTaskId : INVALID_TASK_ID;
     }
 
-    /**
-     * Ensures all visible activities at or below the input activity have the right configuration.
-     */
-    void ensureVisibleActivitiesConfiguration(ActivityRecord start, boolean preserveWindow) {
-        mEnsureVisibleActivitiesConfigHelper.process(start, preserveWindow);
-    }
-
     void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
             @NonNull Configuration parentConfig) {
         computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 2b12e74..d8e18e4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -284,9 +284,9 @@
         }
     }
 
-    void notifyTaskRemovedFromRecents(int taskId, int userId) {
+    void removeAndDeleteSnapshot(int taskId, int userId) {
         mCache.onIdRemoved(taskId);
-        mPersister.onTaskRemovedFromRecents(taskId, userId);
+        mPersister.removeSnapshot(taskId, userId);
     }
 
     void removeSnapshotCache(int taskId) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 3e8c017..233daad 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -67,10 +67,11 @@
      * @param taskId The id of task that has been removed.
      * @param userId The id of the user the task belonged to.
      */
-    void onTaskRemovedFromRecents(int taskId, int userId) {
+    @Override
+    void removeSnapshot(int taskId, int userId) {
         synchronized (mLock) {
             mPersistedTaskIdsSinceLastRemoveObsolete.remove(taskId);
-            super.removeSnap(taskId, userId);
+            super.removeSnapshot(taskId, userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index fbd226e..1456184 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -51,7 +51,8 @@
     final Rect mFrame = new Rect();
 
     /**
-     * The last real frame that was reported to the client.
+     * The frame used to check if mFrame is changed, e.g., moved or resized.  It will be committed
+     * after handling the moving or resizing windows.
      */
     final Rect mLastFrame = new Rect();
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 88f72f9..4a074ff 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -588,6 +588,12 @@
     final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
 
     /**
+     * Windows that their frames are being changed.  Used so we can clear the frame-changing states
+     * after handling the moved or resized windows.
+     */
+    final ArrayList<WindowState> mFrameChangingWindows = new ArrayList<>();
+
+    /**
      * Mapping of displayId to {@link DisplayImePolicy}.
      * Note that this can be accessed without holding the lock.
      */
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 3a793e9..f14a6f9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1200,6 +1200,7 @@
     void updateTrustedOverlay() {
         mInputWindowHandle.setTrustedOverlay(getPendingTransaction(), mSurfaceControl,
                 isWindowTrustedOverlay());
+        mInputWindowHandle.forceChange();
     }
 
     boolean isWindowTrustedOverlay() {
@@ -1346,6 +1347,11 @@
             windowFrames.setContentChanged(true);
         }
 
+        if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)
+                || !windowFrames.mRelFrame.equals(windowFrames.mLastRelFrame)) {
+            mWmService.mFrameChangingWindows.add(this);
+        }
+
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
             if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) {
                 mMovedByResize = true;
@@ -3716,10 +3722,6 @@
         mDragResizingChangeReported = true;
         mWindowFrames.clearReportResizeHints();
 
-        // We update mLastFrame always rather than in the conditional with the last inset
-        // variables, because mFrameSizeChanged only tracks the width and height changing.
-        updateLastFrames();
-
         final int prevRotation = mLastReportedConfiguration
                 .getMergedConfiguration().windowConfiguration.getRotation();
         fillClientWindowFramesAndConfiguration(mClientWindowFrames, mLastReportedConfiguration,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 922f69c..323d387 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -24,6 +24,7 @@
 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_STORAGE_LIMIT_REACHED;
 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED;
 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
 import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT;
 
 import android.Manifest;
@@ -40,7 +41,6 @@
 import android.app.admin.PolicyValue;
 import android.app.admin.TargetUser;
 import android.app.admin.UserRestrictionPolicyKey;
-import android.app.admin.flags.FlagUtils;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -159,7 +159,7 @@
 
         synchronized (mLock) {
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
-            if (FlagUtils.isDevicePolicySizeTrackingEnabled()) {
+            if (devicePolicySizeTrackingEnabled()) {
                 if (!handleAdminPolicySizeLimit(localPolicyState, enforcingAdmin, value,
                         policyDefinition, userId)) {
                     return;
@@ -282,7 +282,7 @@
             }
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
 
-            if (FlagUtils.isDevicePolicySizeTrackingEnabled()) {
+            if (devicePolicySizeTrackingEnabled()) {
                 decreasePolicySizeForAdmin(localPolicyState, enforcingAdmin);
             }
 
@@ -428,7 +428,7 @@
 
         synchronized (mLock) {
             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
-            if (FlagUtils.isDevicePolicySizeTrackingEnabled()) {
+            if (devicePolicySizeTrackingEnabled()) {
                 if (!handleAdminPolicySizeLimit(globalPolicyState, enforcingAdmin, value,
                         policyDefinition, UserHandle.USER_ALL)) {
                     return;
@@ -499,7 +499,7 @@
         synchronized (mLock) {
             PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
 
-            if (FlagUtils.isDevicePolicySizeTrackingEnabled()) {
+            if (devicePolicySizeTrackingEnabled()) {
                 decreasePolicySizeForAdmin(policyState, enforcingAdmin);
             }
 
@@ -1781,7 +1781,7 @@
 
         private void writeEnforcingAdminSizeInner(TypedXmlSerializer serializer)
                 throws IOException {
-            if (FlagUtils.isDevicePolicySizeTrackingEnabled()) {
+            if (devicePolicySizeTrackingEnabled()) {
                 if (mAdminPolicySize != null) {
                     for (int i = 0; i < mAdminPolicySize.size(); i++) {
                         int userId = mAdminPolicySize.keyAt(i);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8509155..5f2d87c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -219,6 +219,7 @@
 import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNER_FAILED;
 import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED;
 import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED;
+import static android.app.admin.flags.Flags.policyEngineMigrationV2Enabled;
 import static android.content.Intent.ACTION_MANAGED_PROFILE_AVAILABLE;
 import static android.content.Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -330,7 +331,6 @@
 import android.app.admin.UnsafeStateException;
 import android.app.admin.UserRestrictionPolicyKey;
 import android.app.admin.WifiSsidPolicy;
-import android.app.admin.flags.FlagUtils;
 import android.app.backup.IBackupManager;
 import android.app.compat.CompatChanges;
 import android.app.role.OnRoleHoldersChangedListener;
@@ -3430,7 +3430,7 @@
             }
 
             revertTransferOwnershipIfNecessaryLocked();
-            if (!FlagUtils.isPolicyEngineMigrationV2Enabled()) {
+            if (!policyEngineMigrationV2Enabled()) {
                 updateUsbDataSignal(mContext, isUsbDataSignalingEnabledInternalLocked());
             }
         }
@@ -21571,7 +21571,7 @@
         Objects.requireNonNull(packageName, "Admin package name must be provided");
         final CallerIdentity caller = getCallerIdentity(packageName);
 
-        if (!FlagUtils.isPolicyEngineMigrationV2Enabled()) {
+        if (!policyEngineMigrationV2Enabled()) {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
                     "USB data signaling can only be controlled by a device owner or "
@@ -21581,7 +21581,7 @@
         }
 
         synchronized (getLockObject()) {
-            if (FlagUtils.isPolicyEngineMigrationV2Enabled()) {
+            if (policyEngineMigrationV2Enabled()) {
                 EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                         /* admin= */ null, MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
                         caller.getPackageName(),
@@ -21621,7 +21621,7 @@
     @Override
     public boolean isUsbDataSignalingEnabled(String packageName) {
         final CallerIdentity caller = getCallerIdentity(packageName);
-        if (FlagUtils.isPolicyEngineMigrationV2Enabled()) {
+        if (policyEngineMigrationV2Enabled()) {
             Boolean enabled = mDevicePolicyEngine.getResolvedPolicy(
                     PolicyDefinition.USB_DATA_SIGNALING,
                     caller.getUserId());
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index 6ff7b26..b63a58a 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -37,6 +37,7 @@
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
 import android.util.Log;
+import android.view.KeyEvent;
 import android.view.WindowManagerGlobal;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -598,6 +599,28 @@
                 false /* orientationPortrait */);
     }
 
+    @Test
+    public void switchesKeyboardLayout_withShortcut_onlyIfImeVisible() throws Exception {
+        setShowImeWithHardKeyboard(true /* enabled */);
+
+        assertThat(mInputMethodService.isInputViewShown()).isFalse();
+        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
+                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
+                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
+                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isFalse();
+
+        verifyInputViewStatusOnMainSync(
+                () -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
+                true /* expected */,
+                true /* inputViewStarted */);
+
+        assertThat(mInputMethodService.isInputViewShown()).isTrue();
+        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
+                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
+                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
+                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isTrue();
+    }
+
     /**
      * This checks that when the system navigation bar is not created (e.g. emulator),
      * then the IME caption bar is also not created.
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 6eacef7..c617ec4 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -58,6 +58,7 @@
         ":PackageManagerTestOverlayTarget",
         ":PackageManagerTestOverlayTargetNoOverlayable",
         ":PackageManagerTestAppDeclaresStaticLibrary",
+        ":PackageManagerTestAppDifferentPkgName",
         ":PackageManagerTestAppStub",
         ":PackageManagerTestAppUsesStaticLibrary",
         ":PackageManagerTestAppVersion1",
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/TamperedUpdatedSystemPackageTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/TamperedUpdatedSystemPackageTest.kt
index c490604..304f605 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/TamperedUpdatedSystemPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/TamperedUpdatedSystemPackageTest.kt
@@ -44,6 +44,10 @@
         private const val VERSION_TWO_ALT_KEY = "PackageManagerTestAppVersion2AltKey.apk"
         private const val VERSION_TWO_ALT_KEY_IDSIG =
                 "PackageManagerTestAppVersion2AltKey.apk.idsig"
+
+        private const val ANOTHER_PKG_NAME = "com.android.server.pm.test.test_app2"
+        private const val ANOTHER_PKG = "PackageManagerTestAppDifferentPkgName.apk"
+
         private const val STRICT_SIGNATURE_CONFIG_PATH =
                 "/system/etc/sysconfig/preinstalled-packages-strict-signature.xml"
         private const val TIMESTAMP_REFERENCE_FILE_PATH = "/data/local/tmp/timestamp.ref"
@@ -74,6 +78,7 @@
     @After
     fun removeApk() {
         device.uninstallPackage(TEST_PKG_NAME)
+        device.uninstallPackage(ANOTHER_PKG_NAME)
     }
 
     @Before
@@ -90,7 +95,9 @@
                     .readText()
                     .replace(
                         "</config>",
-                            "<require-strict-signature package=\"${TEST_PKG_NAME}\"/></config>"
+                            "<require-strict-signature package=\"${TEST_PKG_NAME}\"/>" +
+                            "<require-strict-signature package=\"${ANOTHER_PKG_NAME}\"/>" +
+                            "</config>"
                     )
             writeText(newConfigText)
         }
@@ -146,10 +153,7 @@
                 tempFolder.newFile()
         )
         assertThat(device.installPackage(versionTwoFile, true)).isNull()
-        val baseApkPath = device.executeShellCommand("pm path ${TEST_PKG_NAME}")
-                .lineSequence()
-                .first()
-                .replace("package:", "")
+        val baseApkPath = getBaseApkPath(TEST_PKG_NAME)
         assertThat(baseApkPath).doesNotContain(productPath.toString())
         preparer.pushResourceFile(VERSION_TWO_ALT_KEY_IDSIG, baseApkPath.toString() + ".idsig")
 
@@ -175,4 +179,23 @@
         assertThat(device.executeShellCommand("pm path ${TEST_PKG_NAME}"))
                 .contains(productPath.toString())
     }
+
+    @Test
+    fun allowlistedPackageIsNotASystemApp() {
+        // If an allowlisted package isn't a system app, make sure install and boot still works
+        // normally.
+        assertThat(device.installJavaResourceApk(tempFolder, ANOTHER_PKG, /* reinstall */ false))
+                .isNull()
+        assertThat(getBaseApkPath(ANOTHER_PKG_NAME)).startsWith("/data/app/")
+
+        preparer.reboot()
+        assertThat(getBaseApkPath(ANOTHER_PKG_NAME)).startsWith("/data/app/")
+    }
+
+    private fun getBaseApkPath(pkgName: String): String {
+        return device.executeShellCommand("pm path $pkgName")
+                .lineSequence()
+                .first()
+                .replace("package:", "")
+    }
 }
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
index bee7c40..b826590 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp
@@ -76,3 +76,11 @@
     certificate: ":FrameworksServicesTests_keyset_A_cert",
     v4_signature: true,
 }
+
+android_test_helper_app {
+    name: "PackageManagerTestAppDifferentPkgName",
+    manifest: "AndroidManifestDifferentPkgName.xml",
+    srcs: [
+        "src/**/*.kt",
+    ],
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestDifferentPkgName.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestDifferentPkgName.xml
new file mode 100644
index 0000000..0c5d36e
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestDifferentPkgName.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.pm.test.test_app2"
+    android:versionCode="1"
+    >
+
+    <permission
+        android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
+        android:protectionLevel="normal"
+        />
+
+    <application>
+        <activity android:name="com.android.server.pm.test.test_app.TestActivity"
+            android:label="PackageManagerTestApp" />
+    </application>
+
+</manifest>
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 32e2871..a77a958 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -429,7 +429,7 @@
         SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
         SurfaceControl.DisplayMode[] modes =
                 new SurfaceControl.DisplayMode[]{displayMode};
-        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.refreshRate);
+        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.peakRefreshRate);
         setUpDisplay(display);
         updateAvailableDisplays();
         mAdapter.registerLocked();
@@ -451,7 +451,7 @@
         SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 120f);
         mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
                 new Display.Mode(displayMode2.width, displayMode2.height,
-                        displayMode2.refreshRate));
+                        displayMode2.peakRefreshRate));
         updateAvailableDisplays();
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
         defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
@@ -485,7 +485,7 @@
         SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
         SurfaceControl.DisplayMode[] modes =
                 new SurfaceControl.DisplayMode[]{displayMode};
-        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.refreshRate);
+        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, displayMode.peakRefreshRate);
         setUpDisplay(display);
         updateAvailableDisplays();
         mAdapter.registerLocked();
@@ -947,7 +947,7 @@
         // Set the user preferred display mode
         mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
                 new Display.Mode(
-                        displayMode3.width, displayMode3.height, displayMode3.refreshRate));
+                        displayMode3.width, displayMode3.height, displayMode3.peakRefreshRate));
         updateAvailableDisplays();
         waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
         displayDeviceInfo = mListener.addedDisplays.get(
@@ -992,6 +992,52 @@
     }
 
     @Test
+    public void testGetAndSetDisplayModesDisambiguatesByVsyncRate() throws Exception {
+        SurfaceControl.DisplayMode displayMode1 = createFakeDisplayMode(0, 1920, 1080, 60f, 120f);
+        SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 60f, 60f);
+        SurfaceControl.DisplayMode[] modes =
+                new SurfaceControl.DisplayMode[]{displayMode1, displayMode2};
+        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, 0);
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays).isEmpty();
+
+        DisplayDevice displayDevice = mListener.addedDisplays.get(0);
+
+        DisplayDeviceInfo displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
+        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+        Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode1)).isTrue();
+        assertThat(matches(displayDevice.getSystemPreferredDisplayModeLocked(), displayMode1))
+                .isTrue();
+
+        display.dynamicInfo.preferredBootDisplayMode = 1;
+        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);
+
+        DisplayDevice changedDisplayDevice = mListener.changedDisplays.get(0);
+        changedDisplayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+        displayDeviceInfo = changedDisplayDevice.getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+        assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode1);
+        assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode2);
+
+        assertThat(
+                matches(changedDisplayDevice.getSystemPreferredDisplayModeLocked(), displayMode2))
+                .isTrue();
+    }
+
+    @Test
     public void testHdrSdrRatio_notifiesOnChange() throws Exception {
         FakeDisplay display = new FakeDisplay(PORT_A);
         setUpDisplay(display);
@@ -1230,7 +1276,7 @@
     private void assertModeIsSupported(Display.Mode[] supportedModes,
             SurfaceControl.DisplayMode mode) {
         assertThat(Arrays.stream(supportedModes).anyMatch(
-                x -> x.matches(mode.width, mode.height, mode.refreshRate))).isTrue();
+                x -> x.matches(mode.width, mode.height, mode.peakRefreshRate))).isTrue();
     }
 
     private void assertModeIsSupported(Display.Mode[] supportedModes,
@@ -1244,7 +1290,7 @@
                 + Arrays.toString(supportedModes);
         Truth.assertWithMessage(message)
             .that(Arrays.stream(supportedModes)
-                .anyMatch(x -> x.matches(mode.width, mode.height, mode.refreshRate)
+                .anyMatch(x -> x.matches(mode.width, mode.height, mode.peakRefreshRate)
                         && Arrays.equals(x.getAlternativeRefreshRates(), sortedAlternativeRates)))
                 .isTrue();
     }
@@ -1332,16 +1378,28 @@
 
     private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
             float refreshRate) {
-        return createFakeDisplayMode(id, width, height, refreshRate, /* group */ 0);
+        return createFakeDisplayMode(id, width, height, refreshRate, refreshRate);
     }
 
     private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
-            float refreshRate, int group) {
+                                                                   float refreshRate,
+                                                                    float vsyncRate) {
+        return createFakeDisplayMode(id, width, height, refreshRate, vsyncRate, /* group */ 0);
+    }
+
+    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
+                                                                    float refreshRate, int group) {
+        return createFakeDisplayMode(id, width, height, refreshRate, refreshRate, group);
+    }
+
+    private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
+            float refreshRate, float vsyncRate, int group) {
         final SurfaceControl.DisplayMode mode = new SurfaceControl.DisplayMode();
         mode.id = id;
         mode.width = width;
         mode.height = height;
-        mode.refreshRate = refreshRate;
+        mode.peakRefreshRate = refreshRate;
+        mode.vsyncRate = vsyncRate;
         mode.xDpi = 100;
         mode.yDpi = 100;
         mode.group = group;
@@ -1444,6 +1502,9 @@
 
     private boolean matches(Display.Mode a, SurfaceControl.DisplayMode b) {
         return a.getPhysicalWidth() == b.width && a.getPhysicalHeight() == b.height
-                && Float.floatToIntBits(a.getRefreshRate()) == Float.floatToIntBits(b.refreshRate);
+                && Float.floatToIntBits(a.getRefreshRate())
+                        == Float.floatToIntBits(b.peakRefreshRate)
+                && Float.floatToIntBits(a.getVsyncRate())
+                        == Float.floatToIntBits(b.vsyncRate);
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index c493f84..37fe8d1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -2617,6 +2617,31 @@
         assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj());
     }
 
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoOne_AboveClient_NotStarted() {
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+        doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+        doReturn(app).when(sService).getTopApp();
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
+
+        assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+
+        // Start binding to a service that isn't running yet.
+        ServiceRecord sr = makeServiceRecord(app);
+        sr.app = null;
+        bindService(null, app, sr, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+
+        // Since sr.app is null, this service cannot be in the same process as the
+        // client so we expect the BIND_ABOVE_CLIENT adjustment to take effect.
+        app.mServices.updateHasAboveClientLocked();
+        sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
+        assertTrue(app.mServices.hasAboveClient());
+        assertNotEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+    }
+
     private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
             String packageName, boolean hasShownUi) {
         long now = SystemClock.uptimeMillis();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index 610ea90..7a6ac4e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.doReturn;
@@ -44,6 +45,8 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -122,6 +125,8 @@
 
     private PackageSetting mPackageSetting;
 
+    private PackageManagerService mPackageManagerService;
+
     private PackageArchiver mArchiveManager;
 
     @Before
@@ -130,7 +135,7 @@
         rule.system().stageNominalSystemState();
         when(rule.mocks().getInjector().getPackageInstallerService()).thenReturn(
                 mInstallerService);
-        PackageManagerService pm = spy(new PackageManagerService(rule.mocks().getInjector(),
+        mPackageManagerService = spy(new PackageManagerService(rule.mocks().getInjector(),
                 /* factoryTest= */false,
                 MockSystem.Companion.getDEFAULT_VERSION_INFO().fingerprint,
                 /* isEngBuild= */ false,
@@ -154,15 +159,18 @@
         when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
         when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
                 mLauncherActivityInfos);
-        doReturn(mComputer).when(pm).snapshotComputer();
+        doReturn(mComputer).when(mPackageManagerService).snapshotComputer();
         when(mComputer.getPackageUid(eq(CALLER_PACKAGE), eq(0L), eq(mUserId))).thenReturn(
                 Binder.getCallingUid());
 
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getResourcesForApplication(eq(PACKAGE))).thenReturn(
                 mock(Resources.class));
+        doReturn(new ParceledListSlice<>(List.of(mock(ResolveInfo.class))))
+                .when(mPackageManagerService).queryIntentReceivers(any(), any(), any(), anyLong(),
+                        eq(mUserId));
 
-        mArchiveManager = spy(new PackageArchiver(mContext, pm));
+        mArchiveManager = spy(new PackageArchiver(mContext, mPackageManagerService));
         doReturn(ICON_PATH).when(mArchiveManager).storeIcon(eq(PACKAGE),
                 any(LauncherActivityInfo.class), eq(mUserId), anyInt());
         doReturn(mIcon).when(mArchiveManager).decodeIcon(
@@ -237,6 +245,21 @@
     }
 
     @Test
+    public void archiveApp_installerDoesntSupportUnarchival() {
+        doReturn(new ParceledListSlice<>(List.of()))
+                .when(mPackageManagerService).queryIntentReceivers(any(), any(), any(), anyLong(),
+                        eq(mUserId));
+
+        Exception e = assertThrows(
+                ParcelableException.class,
+                () -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
+                        UserHandle.CURRENT));
+        assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+        assertThat(e.getCause()).hasMessageThat().isEqualTo(
+                "Installer does not support unarchival");
+    }
+
+    @Test
     public void archiveApp_noMainActivities() {
         when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
                 List.of());
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 9f6d7f2..4e6dd06 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -26,11 +26,10 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
-import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS;
-
 import static com.google.common.truth.Truth.assertThat;
 
 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.Mockito.atLeastOnce;
@@ -69,7 +68,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.wm.WindowManagerInternal;
@@ -664,6 +662,28 @@
         verify(mMediaProjectionMetricsLogger).logInitiated(hostUid, sessionCreationSource);
     }
 
+    @Test
+    public void notifyPermissionRequestDisplayed_forwardsToLogger() {
+        int hostUid = 123;
+        mService =
+                new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector);
+
+        mService.notifyPermissionRequestDisplayed(hostUid);
+
+        verify(mMediaProjectionMetricsLogger).logPermissionRequestDisplayed(hostUid);
+    }
+
+    @Test
+    public void notifyAppSelectorDisplayed_forwardsToLogger() {
+        int hostUid = 456;
+        mService =
+                new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector);
+
+        mService.notifyAppSelectorDisplayed(hostUid);
+
+        verify(mMediaProjectionMetricsLogger).logAppSelectorDisplayed(hostUid);
+    }
+
     /**
      * Executes and validates scenario where the consent result indicates the projection ends.
      */
@@ -837,10 +857,69 @@
 
         service.setContentRecordingSession(DISPLAY_SESSION);
 
-        verify(mMediaProjectionMetricsLogger).notifyProjectionStateChange(
+        verify(mMediaProjectionMetricsLogger).logInProgress(
                 projection.uid,
-                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS,
-                FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN
+                DISPLAY_SESSION.getTargetUid()
+        );
+    }
+
+    @Test
+    public void setContentRecordingSession_taskSession_logsCaptureInProgressWithTargetUid()
+            throws Exception {
+        mService.addCallback(mWatcherCallback);
+        MediaProjectionManagerService service =
+                new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector);
+        MediaProjectionManagerService.MediaProjection projection =
+                startProjectionPreconditions(service);
+        projection.start(mIMediaProjectionCallback);
+        doReturn(true)
+                .when(mWindowManagerInternal)
+                .setContentRecordingSession(any(ContentRecordingSession.class));
+        int targetUid = 123455;
+
+        ContentRecordingSession taskSession =
+                ContentRecordingSession.createTaskSession(mock(IBinder.class), targetUid);
+        service.setContentRecordingSession(taskSession);
+
+        verify(mMediaProjectionMetricsLogger).logInProgress(projection.uid, targetUid);
+    }
+
+    @Test
+    public void setContentRecordingSession_failure_doesNotLogCaptureInProgress() throws Exception {
+        mService.addCallback(mWatcherCallback);
+        MediaProjectionManagerService service =
+                new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector);
+        MediaProjectionManagerService.MediaProjection projection =
+                startProjectionPreconditions(service);
+        projection.start(mIMediaProjectionCallback);
+        doReturn(false).when(mWindowManagerInternal).setContentRecordingSession(
+                any(ContentRecordingSession.class));
+
+        service.setContentRecordingSession(DISPLAY_SESSION);
+
+        verify(mMediaProjectionMetricsLogger, never()).logInProgress(
+                anyInt(),
+                anyInt()
+        );
+    }
+
+    @Test
+    public void setContentRecordingSession_sessionNull_doesNotLogCaptureInProgress()
+            throws Exception {
+        mService.addCallback(mWatcherCallback);
+        MediaProjectionManagerService service =
+                new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector);
+        MediaProjectionManagerService.MediaProjection projection =
+                startProjectionPreconditions(service);
+        projection.start(mIMediaProjectionCallback);
+        doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+                any(ContentRecordingSession.class));
+
+        service.setContentRecordingSession(null);
+
+        verify(mMediaProjectionMetricsLogger, never()).logInProgress(
+                anyInt(),
+                anyInt()
         );
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java
index 73b4cc8..410604f 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java
@@ -17,13 +17,16 @@
 package com.android.server.media.projection;
 
 import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS;
 import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED;
+import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED;
 import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED;
 import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -37,7 +40,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -216,21 +218,238 @@
     }
 
     @Test
-    public void logStopped_registersActiveSessionEnded_afterLogging() {
+    public void logStopped_capturingWasInProgress_registersActiveSessionEnded() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
         mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID);
 
-        InOrder inOrder = inOrder(mFrameworkStatsLogWrapper, mTimestampStore);
-        inOrder.verify(mFrameworkStatsLogWrapper)
-                .write(
-                        /* code= */ anyInt(),
-                        /* sessionId= */ anyInt(),
-                        /* state= */ anyInt(),
-                        /* previousState= */ anyInt(),
-                        /* hostUid= */ anyInt(),
-                        /* targetUid= */ anyInt(),
-                        /* timeSinceLastActive= */ anyInt(),
-                        /* creationSource= */ anyInt());
-        inOrder.verify(mTimestampStore).registerActiveSessionEnded();
+        verify(mTimestampStore).registerActiveSessionEnded();
+    }
+
+    @Test
+    public void logStopped_capturingWasNotInProgress_doesNotRegistersActiveSessionEnded() {
+        mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verify(mTimestampStore, never()).registerActiveSessionEnded();
+    }
+
+    @Test
+    public void logInProgress_logsStateChangedAtomId() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyStateChangedAtomIdLogged();
+    }
+
+    @Test
+    public void logInProgress_logsCurrentSessionId() {
+        int currentSessionId = 987;
+        when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId);
+
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifySessionIdLogged(currentSessionId);
+    }
+
+    @Test
+    public void logInProgress_logsStateInProgress() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS);
+    }
+
+    @Test
+    public void logInProgress_logsHostUid() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyHostUidLogged(TEST_HOST_UID);
+    }
+
+    @Test
+    public void logInProgress_logsTargetUid() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyTargetUidLogged(TEST_TARGET_UID);
+    }
+
+    @Test
+    public void logInProgress_logsUnknownTimeSinceLastActive() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyTimeSinceLastActiveSessionLogged(-1);
+    }
+
+    @Test
+    public void logInProgress_logsUnknownSessionCreationSource() {
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+
+        verifyCreationSourceLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    @Test
+    public void logInProgress_logsPreviousState() {
+        mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN);
+
+        mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED);
+
+        mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS);
+
+        mLogger.logInProgress(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsStateChangedAtomId() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyStateChangedAtomIdLogged();
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsCurrentSessionId() {
+        int currentSessionId = 765;
+        when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId);
+
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifySessionIdLogged(currentSessionId);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsStateDisplayed() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsHostUid() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyHostUidLogged(TEST_HOST_UID);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsUnknownTargetUid() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyTargetUidLogged(-2);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsUnknownTimeSinceLastActive() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyTimeSinceLastActiveSessionLogged(-1);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsUnknownSessionCreationSource() {
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+
+        verifyCreationSourceLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    @Test
+    public void logPermissionRequestDisplayed_logsPreviousState() {
+        mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN);
+
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED);
+
+        mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED);
+
+        mLogger.logPermissionRequestDisplayed(TEST_HOST_UID);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsStateChangedAtomId() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyStateChangedAtomIdLogged();
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsCurrentSessionId() {
+        int currentSessionId = 765;
+        when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId);
+
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifySessionIdLogged(currentSessionId);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsStateDisplayed() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsHostUid() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyHostUidLogged(TEST_HOST_UID);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsUnknownTargetUid() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyTargetUidLogged(-2);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsUnknownTimeSinceLastActive() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyTimeSinceLastActiveSessionLogged(-1);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsUnknownSessionCreationSource() {
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+
+        verifyCreationSourceLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN);
+    }
+
+    @Test
+    public void logAppSelectorDisplayed_logsPreviousState() {
+        mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN);
+
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED);
+
+        mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED);
+
+        mLogger.logAppSelectorDisplayed(TEST_HOST_UID);
+        verifyPreviousStateLogged(
+                MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED);
     }
 
     private void verifyStateChangedAtomIdLogged() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 5dfce06..89c6a220 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -974,7 +974,6 @@
         assertThrows(SecurityException.class, userProps::getAlwaysVisible);
     }
 
-
     // Make sure only max managed profiles can be created
     @MediumTest
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
index 61c4d06..270d5df 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -203,5 +203,6 @@
                 mPhoneWindowManager.dispatchUnhandledKey(keyEvent);
             }
         }
+        mPhoneWindowManager.dispatchAllPendingEvents();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index d388db8..f2721a5 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -25,10 +25,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.app.Instrumentation;
 import android.content.Context;
+import android.os.Looper;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
@@ -38,7 +40,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -57,6 +61,7 @@
     private CountDownLatch mLongPressed = new CountDownLatch(1);
     private CountDownLatch mVeryLongPressed = new CountDownLatch(1);
     private CountDownLatch mMultiPressed = new CountDownLatch(1);
+    private BlockingQueue<KeyUpData> mKeyUpQueue = new LinkedBlockingQueue<>();
 
     private final Instrumentation mInstrumentation = getInstrumentation();
     private final Context mContext = mInstrumentation.getTargetContext();
@@ -76,7 +81,7 @@
     public void setUp() {
         mInstrumentation.runOnMainSync(
                 () -> {
-                    mDetector = SingleKeyGestureDetector.get(mContext);
+                    mDetector = SingleKeyGestureDetector.get(mContext, Looper.myLooper());
                     initSingleKeyGestureRules();
                 });
 
@@ -134,6 +139,11 @@
                         assertTrue(mMaxMultiPressCount >= count);
                         assertEquals(mExpectedMultiPressCount, count);
                     }
+
+                    @Override
+                    void onKeyUp(long eventTime, int multiPressCount) {
+                        mKeyUpQueue.add(new KeyUpData(KEYCODE_POWER, multiPressCount));
+                    }
                 });
 
         mDetector.addRule(
@@ -167,12 +177,27 @@
                     }
 
                     @Override
+                    void onKeyUp(long eventTime, int multiPressCount) {
+                        mKeyUpQueue.add(new KeyUpData(KEYCODE_BACK, multiPressCount));
+                    }
+
+                    @Override
                     void onLongPress(long downTime) {
                         mLongPressed.countDown();
                     }
                 });
     }
 
+    private static class KeyUpData {
+        public final int keyCode;
+        public final int pressCount;
+
+        KeyUpData(int keyCode, int pressCount) {
+            this.keyCode = keyCode;
+            this.pressCount = pressCount;
+        }
+    }
+
     private void pressKey(int keyCode, long pressTime) {
         pressKey(keyCode, pressTime, true /* interactive */);
     }
@@ -250,6 +275,21 @@
     }
 
     @Test
+    public void testOnKeyUp() throws InterruptedException {
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
+
+        verifyKeyUpData(KEYCODE_POWER, 1 /* expectedMultiPressCount */);
+    }
+
+    private void verifyKeyUpData(int expectedKeyCode, int expectedMultiPressCount)
+            throws InterruptedException {
+        KeyUpData keyUpData = mKeyUpQueue.poll(mWaitTimeout, TimeUnit.MILLISECONDS);
+        assertNotNull(keyUpData);
+        assertEquals(expectedKeyCode, keyUpData.keyCode);
+        assertEquals(expectedMultiPressCount, keyUpData.pressCount);
+    }
+
+    @Test
     public void testNonInteractive() throws InterruptedException {
         // Disallow short press behavior from non interactive.
         mAllowNonInteractiveForPress = false;
@@ -314,6 +354,33 @@
     }
 
     @Test
+    public void testOnKeyUp_Pressure() throws InterruptedException {
+        final HandlerThread handlerThread =
+                new HandlerThread("testInputReader", Process.THREAD_PRIORITY_DISPLAY);
+        handlerThread.start();
+        Handler newHandler = new Handler(handlerThread.getLooper());
+        try {
+            // To make sure we won't get any unexpected multi-press count.
+            for (int i = 0; i < 5; i++) {
+                newHandler.runWithScissors(
+                        () -> {
+                            pressKey(KEYCODE_POWER, 0 /* pressTime */);
+                            pressKey(KEYCODE_POWER, 0 /* pressTime */);
+                        },
+                        mWaitTimeout);
+                newHandler.runWithScissors(
+                        () -> pressKey(KEYCODE_BACK, 0 /* pressTime */), mWaitTimeout);
+
+                verifyKeyUpData(KEYCODE_POWER, 1 /* expectedMultiPressCount */);
+                verifyKeyUpData(KEYCODE_POWER, 2 /* expectedMultiPressCount */);
+                verifyKeyUpData(KEYCODE_BACK, 1 /* expectedMultiPressCount */);
+            }
+        } finally {
+            handlerThread.quitSafely();
+        }
+    }
+
+    @Test
     public void testUpdateRule() throws InterruptedException {
         // Power key rule doesn't allow the long press gesture.
         mLongPressOnPowerBehavior = false;
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 261d3cc..e26260a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -118,7 +118,6 @@
 import java.util.function.Supplier;
 
 class TestPhoneWindowManager {
-    private static final long SHORTCUT_KEY_DELAY_MILLIS = 150;
     private static final long TEST_SINGLE_KEY_DELAY_MILLIS
             = SingleKeyGestureDetector.MULTI_PRESS_TIMEOUT + 1000L * HW_TIMEOUT_MULTIPLIER;
 
@@ -188,7 +187,7 @@
         MockitoAnnotations.initMocks(this);
         mHandler = new Handler(mTestLooper.getLooper());
         mContext = mockingDetails(context).isSpy() ? context : spy(context);
-        mHandler.post(() -> setUp(supportSettingsUpdate));
+        setUp(supportSettingsUpdate);
         mTestLooper.dispatchAll();
     }
 
@@ -306,6 +305,10 @@
         mMockitoSession.finishMocking();
     }
 
+    void dispatchAllPendingEvents() {
+        mTestLooper.dispatchAll();
+    }
+
     // Override accessibility setting and perform function.
     private void overrideLaunchAccessibility() {
         doReturn(true).when(mAccessibilityShortcutController)
@@ -446,6 +449,7 @@
         doNothing().when(mPhoneWindowManager).sendCloseSystemWindows();
         doReturn(true).when(mPhoneWindowManager).isUserSetupComplete();
         doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
+        doReturn(mSearchManager).when(mContext).getSystemService(eq(SearchManager.class));
     }
 
     void overrideSearchManager(SearchManager searchManager) {
@@ -500,29 +504,24 @@
      */
     void assertTakeScreenshotCalled() {
         mTestLooper.dispatchAll();
-        verify(mDisplayPolicy, timeout(SHORTCUT_KEY_DELAY_MILLIS))
-                .takeScreenshot(anyInt(), anyInt());
+        verify(mDisplayPolicy).takeScreenshot(anyInt(), anyInt());
     }
 
     void assertShowGlobalActionsCalled() {
         mTestLooper.dispatchAll();
         verify(mPhoneWindowManager).showGlobalActions();
-        verify(mGlobalActions, timeout(SHORTCUT_KEY_DELAY_MILLIS))
-                .showDialog(anyBoolean(), anyBoolean());
-        verify(mPowerManager, timeout(SHORTCUT_KEY_DELAY_MILLIS))
-                .userActivity(anyLong(), anyBoolean());
+        verify(mGlobalActions).showDialog(anyBoolean(), anyBoolean());
+        verify(mPowerManager).userActivity(anyLong(), anyBoolean());
     }
 
     void assertVolumeMute() {
         mTestLooper.dispatchAll();
-        verify(mAudioManagerInternal, timeout(SHORTCUT_KEY_DELAY_MILLIS))
-                .silenceRingerModeInternal(eq("volume_hush"));
+        verify(mAudioManagerInternal).silenceRingerModeInternal(eq("volume_hush"));
     }
 
     void assertAccessibilityKeychordCalled() {
         mTestLooper.dispatchAll();
-        verify(mAccessibilityShortcutController,
-                timeout(SHORTCUT_KEY_DELAY_MILLIS)).performAccessibilityShortcut();
+        verify(mAccessibilityShortcutController).performAccessibilityShortcut();
     }
 
     void assertDreamRequest() {
@@ -532,14 +531,12 @@
 
     void assertPowerSleep() {
         mTestLooper.dispatchAll();
-        verify(mPowerManager,
-                timeout(SHORTCUT_KEY_DELAY_MILLIS)).goToSleep(anyLong(), anyInt(), anyInt());
+        verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt());
     }
 
     void assertPowerWakeUp() {
         mTestLooper.dispatchAll();
-        verify(mPowerManager,
-                timeout(SHORTCUT_KEY_DELAY_MILLIS)).wakeUp(anyLong(), anyInt(), anyString());
+        verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
     }
 
     void assertNoPowerSleep() {
@@ -556,7 +553,7 @@
 
     void assertSearchManagerLaunchAssist() {
         mTestLooper.dispatchAll();
-        verify(mSearchManager, timeout(SHORTCUT_KEY_DELAY_MILLIS)).launchAssist(any());
+        verify(mSearchManager).launchAssist(any());
     }
 
     void assertLaunchCategory(String category) {
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 40ac7b1c..bdbfb7a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2627,6 +2627,13 @@
         // Can specify orientation if the current orientation candidate is orientation behind.
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE,
                 activity.getOrientation(SCREEN_ORIENTATION_BEHIND));
+
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setActivityTheme(android.R.style.Theme_Translucent)
+                .setCreateTask(true).build();
+        assertFalse(translucentActivity.providesOrientation());
+        translucentActivity.setOccludesParent(true);
+        assertTrue(translucentActivity.providesOrientation());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 6a738be..9f58491 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -41,7 +41,6 @@
 
 import com.android.server.testutils.StubTransaction;
 import com.android.server.wm.utils.MockAnimationAdapter;
-import com.android.window.flags.Flags;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -150,7 +149,7 @@
         mHost = new MockSurfaceBuildingContainer(mWm);
         mTransaction = spy(StubTransaction.class);
         mChild = new TestWindowContainer(mWm);
-        if (Flags.dimmerRefactor()) {
+        if (Dimmer.DIMMER_REFACTOR) {
             sTestAnimation = spy(new MockAnimationAdapter());
             mDimmer = new SmoothDimmer(mHost, new MockAnimationAdapterFactory());
         } else {
@@ -177,7 +176,7 @@
 
     @Test
     public void testDimBelowWithChildSurfaceCreatesSurfaceBelowChild_Smooth() {
-        assumeTrue(Flags.dimmerRefactor());
+        assumeTrue(Dimmer.DIMMER_REFACTOR);
         final float alpha = 0.7f;
         final int blur = 50;
         mHost.addChild(mChild, 0);
@@ -197,7 +196,7 @@
 
     @Test
     public void testDimBelowWithChildSurfaceCreatesSurfaceBelowChild_Legacy() {
-        assumeFalse(Flags.dimmerRefactor());
+        assumeFalse(Dimmer.DIMMER_REFACTOR);
         final float alpha = 0.7f;
         mHost.addChild(mChild, 0);
         mDimmer.adjustAppearance(mChild, alpha, 20);
@@ -212,7 +211,7 @@
 
     @Test
     public void testDimBelowWithChildSurfaceDestroyedWhenReset_Smooth() {
-        assumeTrue(Flags.dimmerRefactor());
+        assumeTrue(Dimmer.DIMMER_REFACTOR);
         mHost.addChild(mChild, 0);
 
         final float alpha = 0.8f;
@@ -232,7 +231,7 @@
 
     @Test
     public void testDimBelowWithChildSurfaceDestroyedWhenReset_Legacy() {
-        assumeFalse(Flags.dimmerRefactor());
+        assumeFalse(Dimmer.DIMMER_REFACTOR);
         mHost.addChild(mChild, 0);
 
         final float alpha = 0.8f;
@@ -292,7 +291,7 @@
 
     @Test
     public void testRemoveDimImmediately_Smooth() {
-        assumeTrue(Flags.dimmerRefactor());
+        assumeTrue(Dimmer.DIMMER_REFACTOR);
         mHost.addChild(mChild, 0);
         mDimmer.adjustAppearance(mChild, 1, 2);
         mDimmer.adjustRelativeLayer(mChild, -1);
@@ -312,7 +311,7 @@
 
     @Test
     public void testRemoveDimImmediately_Legacy() {
-        assumeFalse(Flags.dimmerRefactor());
+        assumeFalse(Dimmer.DIMMER_REFACTOR);
         mHost.addChild(mChild, 0);
         mDimmer.adjustAppearance(mChild, 1, 0);
         mDimmer.adjustRelativeLayer(mChild, -1);
@@ -332,7 +331,7 @@
 
     @Test
     public void testDimmerWithBlurUpdatesTransaction_Legacy() {
-        assumeFalse(Flags.dimmerRefactor());
+        assumeFalse(Dimmer.DIMMER_REFACTOR);
         mHost.addChild(mChild, 0);
 
         final int blurRadius = 50;
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 5f92fd5..0d4c443 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -676,60 +676,59 @@
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
     public void testOverrideOrientationIfNeeded_portraitOverrideEnabled_returnsPortrait()
             throws Exception {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR})
     public void testOverrideOrientationIfNeeded_portraitOverrideEnabled_returnsNosensor() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_NOSENSOR);
+        assertEquals(SCREEN_ORIENTATION_NOSENSOR, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR})
     public void testOverrideOrientationIfNeeded_nosensorOverride_orientationFixed_returnsUnchanged() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE})
     public void testOverrideOrientationIfNeeded_reverseLandscapeOverride_orientationPortraitOrUndefined_returnsUnchanged() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE})
     public void testOverrideOrientationIfNeeded_reverseLandscapeOverride_orientationLandscape_returnsReverseLandscape() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_LANDSCAPE),
-                SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_LANDSCAPE));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
     public void testOverrideOrientationIfNeeded_portraitOverride_orientationFixed_returnsUnchanged() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_NOSENSOR), SCREEN_ORIENTATION_NOSENSOR);
+        assertEquals(SCREEN_ORIENTATION_NOSENSOR, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_NOSENSOR));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT, OVERRIDE_ANY_ORIENTATION})
     public void testOverrideOrientationIfNeeded_portraitAndIgnoreFixedOverrides_returnsPortrait() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_NOSENSOR), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_NOSENSOR));
     }
 
     @Test
     @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR, OVERRIDE_ANY_ORIENTATION})
     public void testOverrideOrientationIfNeeded_noSensorAndIgnoreFixedOverrides_returnsNosensor() {
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_NOSENSOR);
+        assertEquals(SCREEN_ORIENTATION_NOSENSOR, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
     }
 
     @Test
@@ -740,8 +739,8 @@
 
         mController = new LetterboxUiController(mWm, mActivity);
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
@@ -760,8 +759,8 @@
         doReturn(false).when(mDisplayContent.mDisplayRotationCompatPolicy)
                 .isActivityEligibleForOrientationOverride(eq(mActivity));
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
@@ -780,8 +779,8 @@
         doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
                 .isActivityEligibleForOrientationOverride(eq(mActivity));
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
@@ -789,8 +788,8 @@
         spyOn(mController);
         doReturn(true).when(mController).shouldApplyUserFullscreenOverride();
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_USER);
+        assertEquals(SCREEN_ORIENTATION_USER, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     @Test
@@ -799,8 +798,8 @@
         spyOn(mController);
         doReturn(true).when(mController).shouldApplyUserFullscreenOverride();
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_USER);
+        assertEquals(SCREEN_ORIENTATION_USER, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
     }
 
     @Test
@@ -808,8 +807,8 @@
         spyOn(mController);
         doReturn(false).when(mController).shouldApplyUserFullscreenOverride();
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_PORTRAIT));
     }
 
     @Test
@@ -817,15 +816,15 @@
         spyOn(mController);
         doReturn(true).when(mController).shouldApplyUserMinAspectRatioOverride();
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_LOCKED), SCREEN_ORIENTATION_PORTRAIT);
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_LOCKED));
 
         // unchanged if orientation is specified
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_LANDSCAPE), SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_LANDSCAPE));
     }
 
     @Test
@@ -833,8 +832,8 @@
         spyOn(mController);
         doReturn(false).when(mController).shouldApplyUserMinAspectRatioOverride();
 
-        assertEquals(mController.overrideOrientationIfNeeded(
-                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED));
     }
 
     // shouldApplyUser...Override
@@ -1286,16 +1285,16 @@
         mActivity = setUpActivityWithComponent();
         mController = new LetterboxUiController(mWm, mActivity);
 
-        assertEquals(mController.getFixedOrientationLetterboxAspectRatio(
-                mActivity.getParent().getConfiguration()), 1.5f, /* delta */ 0.01);
+        assertEquals(1.5f, mController.getFixedOrientationLetterboxAspectRatio(
+                mActivity.getParent().getConfiguration()), /* delta */ 0.01);
 
         spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
         doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
                 .isTreatmentEnabledForActivity(eq(mActivity));
 
-        assertEquals(mController.getFixedOrientationLetterboxAspectRatio(
-                mActivity.getParent().getConfiguration()), mController.getSplitScreenAspectRatio(),
-                /* delta */  0.01);
+        assertEquals(mController.getSplitScreenAspectRatio(),
+                mController.getFixedOrientationLetterboxAspectRatio(
+                        mActivity.getParent().getConfiguration()), /* delta */  0.01);
     }
 
     private void mockThatProperty(String propertyName, boolean value) throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 2597465..03188f8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -208,15 +208,18 @@
     private void setUpSystemCore() {
         doReturn(mock(Watchdog.class)).when(Watchdog::getInstance);
         doAnswer(invocation -> {
-            // Exclude CONSTRAIN_DISPLAY_APIS because ActivityRecord#sConstrainDisplayApisConfig
-            // only registers once and it doesn't reference to outside.
-            if (!NAMESPACE_CONSTRAIN_DISPLAY_APIS.equals(invocation.getArgument(0))) {
-                mDeviceConfigListeners.add(invocation.getArgument(2));
+            if ("addOnPropertiesChangedListener".equals(invocation.getMethod().getName())) {
+                // Exclude CONSTRAIN_DISPLAY_APIS because ActivityRecord#sConstrainDisplayApisConfig
+                // only registers once and it doesn't reference to outside.
+                if (!NAMESPACE_CONSTRAIN_DISPLAY_APIS.equals(invocation.getArgument(0))) {
+                    mDeviceConfigListeners.add(invocation.getArgument(2));
+                }
+                // SizeCompatTests uses setNeverConstrainDisplayApisFlag, and ActivityRecordTests
+                // uses splash_screen_exception_list. So still execute real registration.
             }
-            // SizeCompatTests uses setNeverConstrainDisplayApisFlag, and ActivityRecordTests
-            // uses splash_screen_exception_list. So still execute real registration.
             return invocation.callRealMethod();
-        }).when(() -> DeviceConfig.addOnPropertiesChangedListener(anyString(), any(), any()));
+        }).when(() -> DeviceConfig.addOnPropertiesChangedListener(
+                anyString(), any(), any(DeviceConfig.OnPropertiesChangedListener.class)));
 
         mContext = getInstrumentation().getTargetContext();
         spyOn(mContext);
@@ -397,20 +400,24 @@
     }
 
     private void tearDown() {
-        for (int i = mWmService.mRoot.getChildCount() - 1; i >= 0; i--) {
-            final DisplayContent dc = mWmService.mRoot.getChildAt(i);
-            // Unregister SettingsObserver.
-            dc.getDisplayPolicy().release();
-            // Unregister SensorEventListener (foldable device may register for hinge angle).
-            dc.getDisplayRotation().onDisplayRemoved();
-            if (dc.mDisplayRotationCompatPolicy != null) {
-                dc.mDisplayRotationCompatPolicy.dispose();
+        if (mWmService != null) {
+            for (int i = mWmService.mRoot.getChildCount() - 1; i >= 0; i--) {
+                final DisplayContent dc = mWmService.mRoot.getChildAt(i);
+                // Unregister SettingsObserver.
+                dc.getDisplayPolicy().release();
+                // Unregister SensorEventListener (foldable device may register for hinge angle).
+                dc.getDisplayRotation().onDisplayRemoved();
+                if (dc.mDisplayRotationCompatPolicy != null) {
+                    dc.mDisplayRotationCompatPolicy.dispose();
+                }
             }
         }
 
-        // Unregister display listener from root to avoid issues with subsequent tests.
-        mContext.getSystemService(DisplayManager.class)
-                .unregisterDisplayListener(mAtmService.mRootWindowContainer);
+        if (mAtmService != null) {
+            // Unregister display listener from root to avoid issues with subsequent tests.
+            mContext.getSystemService(DisplayManager.class)
+                    .unregisterDisplayListener(mAtmService.mRootWindowContainer);
+        }
 
         for (int i = mDeviceConfigListeners.size() - 1; i >= 0; i--) {
             DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListeners.get(i));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 13a4c11..8fecbb9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -96,7 +96,7 @@
     @Test
     public void testTaskRemovedFromRecents() {
         mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
-        mPersister.onTaskRemovedFromRecents(1, mTestUserId);
+        mPersister.removeSnapshot(1, mTestUserId);
         mSnapshotPersistQueue.waitForQueueEmpty();
         assertFalse(new File(FILES_DIR.getPath() + "/snapshots/1.proto").exists());
         assertFalse(new File(FILES_DIR.getPath() + "/snapshots/1.jpg").exists());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 08438c8..267bec9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -19,6 +19,7 @@
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.os.Build.HW_TIMEOUT_MULTIPLIER;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -79,7 +80,7 @@
     private ImageReader mImageReader;
     private final ArrayList<Activity> mStartedActivities = new ArrayList<>();
 
-    private static final int WAIT_TIMEOUT_MS = 5000;
+    private static final int WAIT_TIMEOUT_MS = 5000 * HW_TIMEOUT_MULTIPLIER;
     private static final Object sLock = new Object();
 
     @Before
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 9146889..e0ed642 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1184,6 +1184,7 @@
         private boolean mCreateTask = false;
         private Task mParentTask;
         private int mActivityFlags;
+        private int mActivityTheme;
         private int mLaunchMode;
         private int mResizeMode = RESIZE_MODE_RESIZEABLE;
         private float mMaxAspectRatio;
@@ -1232,6 +1233,14 @@
             return this;
         }
 
+        ActivityBuilder setActivityTheme(int theme) {
+            mActivityTheme = theme;
+            // Use the real package of test so it can get a valid context for theme.
+            mComponent = ComponentName.createRelative(mService.mContext.getPackageName(),
+                    DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
+            return this;
+        }
+
         ActivityBuilder setActivityFlags(int flags) {
             mActivityFlags = flags;
             return this;
@@ -1381,6 +1390,9 @@
             if (mTargetActivity != null) {
                 aInfo.targetActivity = mTargetActivity;
             }
+            if (mActivityTheme != 0) {
+                aInfo.theme = mActivityTheme;
+            }
             aInfo.flags |= mActivityFlags;
             aInfo.launchMode = mLaunchMode;
             aInfo.resizeMode = mResizeMode;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java b/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java
new file mode 100644
index 0000000..31418d6
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.usage;
+
+import android.os.Looper;
+import android.os.Trace;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.ServiceThread;
+
+/**
+ * Shared singleton default priority thread for usage stats message handling.
+ */
+public class UsageStatsHandlerThread extends ServiceThread {
+    private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000;
+    private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
+
+    private static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static UsageStatsHandlerThread sInstance;
+
+    private UsageStatsHandlerThread() {
+        super("android.usagestats", android.os.Process.THREAD_PRIORITY_DEFAULT,
+                /* allowIo= */ true);
+    }
+
+    @GuardedBy("sLock")
+    private static void ensureThreadLocked() {
+        if (sInstance != null) {
+            return;
+        }
+
+        sInstance = new UsageStatsHandlerThread();
+        sInstance.start();
+        final Looper looper = sInstance.getLooper();
+        looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
+        looper.setSlowLogThresholdMs(
+                SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
+    }
+
+    /**
+     * Obtain a singleton instance of the UsageStatsHandlerThread.
+     */
+    public static UsageStatsHandlerThread get() {
+        synchronized (sLock) {
+            ensureThreadLocked();
+            return sInstance;
+        }
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 55b5d11..e413663 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -202,6 +202,7 @@
     static final int MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK = 8;
     static final int MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED = 9;
     static final int MSG_UID_REMOVED = 10;
+    static final int MSG_USER_STARTED = 11;
 
     private final Object mLock = new Object();
     private Handler mHandler;
@@ -334,7 +335,7 @@
         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
         mPackageManager = getContext().getPackageManager();
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-        mHandler = new H(BackgroundThread.get().getLooper());
+        mHandler = getUsageEventProcessingHandler();
         mIoHandler = new Handler(IoThread.get().getLooper(), mIoHandlerCallback);
 
         mAppStandby = mInjector.getAppStandbyController(getContext());
@@ -380,10 +381,12 @@
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
-        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL,
-                filter, null, /* Handler scheduler */ null);
+        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
+                null, /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);
+
         getContext().registerReceiverAsUser(new UidRemovedReceiver(), UserHandle.ALL,
-                new IntentFilter(ACTION_UID_REMOVED), null, /* Handler scheduler */ null);
+                new IntentFilter(ACTION_UID_REMOVED), null,
+                /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);
 
         mRealTimeSnapshot = SystemClock.elapsedRealtime();
         mSystemTimeSnapshot = System.currentTimeMillis();
@@ -471,6 +474,14 @@
         }
     }
 
+    private Handler getUsageEventProcessingHandler() {
+        if (Flags.useDedicatedHandlerThread()) {
+            return new H(UsageStatsHandlerThread.get().getLooper());
+        } else {
+            return new H(BackgroundThread.get().getLooper());
+        }
+    }
+
     private void onUserUnlocked(int userId) {
         // fetch the installed packages outside the lock so it doesn't block package manager.
         final HashMap<String, Long> installedPackages = getInstalledPackages(userId);
@@ -618,7 +629,7 @@
                 }
             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                 if (userId >= 0) {
-                    mAppStandby.postCheckIdleStates(userId);
+                    mHandler.obtainMessage(MSG_USER_STARTED, userId, 0).sendToTarget();
                 }
             }
         }
@@ -1554,8 +1565,7 @@
         synchronized (mLaunchTimeAlarmQueues) {
             LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId);
             if (alarmQueue == null) {
-                alarmQueue = new LaunchTimeAlarmQueue(
-                    userId, getContext(), BackgroundThread.get().getLooper());
+                alarmQueue = new LaunchTimeAlarmQueue(userId, getContext(), mHandler.getLooper());
                 mLaunchTimeAlarmQueues.put(userId, alarmQueue);
             }
 
@@ -2040,6 +2050,9 @@
                 case MSG_UID_REMOVED:
                     mResponseStatsTracker.onUidRemoved(msg.arg1);
                     break;
+                case MSG_USER_STARTED:
+                    mAppStandby.postCheckIdleStates(msg.arg1);
+                    break;
                 case MSG_PACKAGE_REMOVED:
                     onPackageRemoved(msg.arg1, (String) msg.obj);
                     break;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 540cecf..038b93f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9681,7 +9681,6 @@
      *
      * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED
      * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT
-     * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED
      */
     public static final String
             KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 73220c3..c0d6b30 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17483,6 +17483,8 @@
      * {@link CarrierConfigManager
      * #KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG}
      * and return {@link #PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED}.
+     *
+     * @hide
      */
     public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED = 16;